简体   繁体   English

如何使用 python 更改我的桌面背景?

[英]How can I change my desktop background with python?

How can I change my desktop background with python?如何使用 python 更改我的桌面背景?

I want to do it in both Windows and Linux.我想在 Windows 和 Linux 中都这样做。

On Windows with python2.5 or higher, use ctypes to load user32.dll and call SystemParametersInfo() with SPI_SETDESKWALLPAPER action.在具有 python2.5 或更高版本的 Windows 上,使用 ctypes 加载 user32.dll 并使用 SPI_SETDESKWALLPAPER 操作调用SystemParametersInfo()

For example:例如:

import ctypes
SPI_SETDESKWALLPAPER = 20 
ctypes.windll.user32.SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, "image.jpg" , 0)

For Python3.5, SystemParametersInfoA doesn't work.对于 Python3.5,SystemParametersInfoA 不起作用。 Use SystemParametersInfoW.使用 SystemParametersInfoW。

import ctypes
ctypes.windll.user32.SystemParametersInfoW(20, 0, "absolute path" , 0)

I use the following method in one of my initial projects:我在我的一个初始项目中使用以下方法:

    def set_wallpaper(self,file_loc, first_run):
        # Note: There are two common Linux desktop environments where 
        # I have not been able to set the desktop background from 
        # command line: KDE, Enlightenment
        desktop_env = self.get_desktop_environment()
        try:
            if desktop_env in ["gnome", "unity", "cinnamon"]:
                uri = "'file://%s'" % file_loc
                try:
                    SCHEMA = "org.gnome.desktop.background"
                    KEY = "picture-uri"
                    gsettings = Gio.Settings.new(SCHEMA)
                    gsettings.set_string(KEY, uri)
                except:
                    args = ["gsettings", "set", "org.gnome.desktop.background", "picture-uri", uri]
                    subprocess.Popen(args)
            elif desktop_env=="mate":
                try: # MATE >= 1.6
                    # info from http://wiki.mate-desktop.org/docs:gsettings
                    args = ["gsettings", "set", "org.mate.background", "picture-filename", "'%s'" % file_loc]
                    subprocess.Popen(args)
                except: # MATE < 1.6
                    # From https://bugs.launchpad.net/variety/+bug/1033918
                    args = ["mateconftool-2","-t","string","--set","/desktop/mate/background/picture_filename",'"%s"' %file_loc]
                    subprocess.Popen(args)
            elif desktop_env=="gnome2": # Not tested
                # From https://bugs.launchpad.net/variety/+bug/1033918
                args = ["gconftool-2","-t","string","--set","/desktop/gnome/background/picture_filename", '"%s"' %file_loc]
                subprocess.Popen(args)
            ## KDE4 is difficult
            ## see http://blog.zx2c4.com/699 for a solution that might work
            elif desktop_env in ["kde3", "trinity"]:
                # From http://ubuntuforums.org/archive/index.php/t-803417.html
                args = 'dcop kdesktop KBackgroundIface setWallpaper 0 "%s" 6' % file_loc
                subprocess.Popen(args,shell=True)
            elif desktop_env=="xfce4":
                #From http://www.commandlinefu.com/commands/view/2055/change-wallpaper-for-xfce4-4.6.0
                if first_run:
                    args0 = ["xfconf-query", "-c", "xfce4-desktop", "-p", "/backdrop/screen0/monitor0/image-path", "-s", file_loc]
                    args1 = ["xfconf-query", "-c", "xfce4-desktop", "-p", "/backdrop/screen0/monitor0/image-style", "-s", "3"]
                    args2 = ["xfconf-query", "-c", "xfce4-desktop", "-p", "/backdrop/screen0/monitor0/image-show", "-s", "true"]
                    subprocess.Popen(args0)
                    subprocess.Popen(args1)
                    subprocess.Popen(args2)
                args = ["xfdesktop","--reload"]
                subprocess.Popen(args)
            elif desktop_env=="razor-qt": #TODO: implement reload of desktop when possible
                if first_run:
                    desktop_conf = configparser.ConfigParser()
                    # Development version
                    desktop_conf_file = os.path.join(self.get_config_dir("razor"),"desktop.conf") 
                    if os.path.isfile(desktop_conf_file):
                        config_option = r"screens\1\desktops\1\wallpaper"
                    else:
                        desktop_conf_file = os.path.join(self.get_home_dir(),".razor/desktop.conf")
                        config_option = r"desktops\1\wallpaper"
                    desktop_conf.read(os.path.join(desktop_conf_file))
                    try:
                        if desktop_conf.has_option("razor",config_option): #only replacing a value
                            desktop_conf.set("razor",config_option,file_loc)
                            with codecs.open(desktop_conf_file, "w", encoding="utf-8", errors="replace") as f:
                                desktop_conf.write(f)
                    except:
                        pass
                else:
                    #TODO: reload desktop when possible
                    pass 
            elif desktop_env in ["fluxbox","jwm","openbox","afterstep"]:
                #http://fluxbox-wiki.org/index.php/Howto_set_the_background
                # used fbsetbg on jwm too since I am too lazy to edit the XML configuration 
                # now where fbsetbg does the job excellent anyway. 
                # and I have not figured out how else it can be set on Openbox and AfterSTep
                # but fbsetbg works excellent here too.
                try:
                    args = ["fbsetbg", file_loc]
                    subprocess.Popen(args)
                except:
                    sys.stderr.write("ERROR: Failed to set wallpaper with fbsetbg!\n")
                    sys.stderr.write("Please make sre that You have fbsetbg installed.\n")
            elif desktop_env=="icewm":
                # command found at http://urukrama.wordpress.com/2007/12/05/desktop-backgrounds-in-window-managers/
                args = ["icewmbg", file_loc]
                subprocess.Popen(args)
            elif desktop_env=="blackbox":
                # command found at http://blackboxwm.sourceforge.net/BlackboxDocumentation/BlackboxBackground
                args = ["bsetbg", "-full", file_loc]
                subprocess.Popen(args)
            elif desktop_env=="lxde":
                args = "pcmanfm --set-wallpaper %s --wallpaper-mode=scaled" % file_loc
                subprocess.Popen(args,shell=True)
            elif desktop_env=="windowmaker":
                # From http://www.commandlinefu.com/commands/view/3857/set-wallpaper-on-windowmaker-in-one-line
                args = "wmsetbg -s -u %s" % file_loc
                subprocess.Popen(args,shell=True)
            ## NOT TESTED BELOW - don't want to mess things up ##
            #elif desktop_env=="enlightenment": # I have not been able to make it work on e17. On e16 it would have been something in this direction
            #    args = "enlightenment_remote -desktop-bg-add 0 0 0 0 %s" % file_loc
            #    subprocess.Popen(args,shell=True)
            #elif desktop_env=="windows": #Not tested since I do not run this on Windows
            #    #From https://stackoverflow.com/questions/1977694/change-desktop-background
            #    import ctypes
            #    SPI_SETDESKWALLPAPER = 20
            #    ctypes.windll.user32.SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, file_loc , 0)
            #elif desktop_env=="mac": #Not tested since I do not have a mac
            #    #From https://stackoverflow.com/questions/431205/how-can-i-programatically-change-the-background-in-mac-os-x
            #    try:
            #        from appscript import app, mactypes
            #        app('Finder').desktop_picture.set(mactypes.File(file_loc))
            #    except ImportError:
            #        #import subprocess
            #        SCRIPT = """/usr/bin/osascript<<END
            #        tell application "Finder" to
            #        set desktop picture to POSIX file "%s"
            #        end tell
            #        END"""
            #        subprocess.Popen(SCRIPT%file_loc, shell=True)
            else:
                if first_run: #don't spam the user with the same message over and over again
                    sys.stderr.write("Warning: Failed to set wallpaper. Your desktop environment is not supported.")
                    sys.stderr.write("You can try manually to set Your wallpaper to %s" % file_loc)
                return False
            return True
        except:
            sys.stderr.write("ERROR: Failed to set wallpaper. There might be a bug.\n")
            return False

    def get_config_dir(self, app_name=APP_NAME):
        if "XDG_CONFIG_HOME" in os.environ:
            confighome = os.environ['XDG_CONFIG_HOME'] 
        elif "APPDATA" in os.environ: # On Windows
            confighome = os.environ['APPDATA'] 
        else:
            try:
                from xdg import BaseDirectory   
                confighome =  BaseDirectory.xdg_config_home
            except ImportError: # Most likely a Linux/Unix system anyway
                confighome =  os.path.join(self.get_home_dir(),".config")
        configdir = os.path.join(confighome,app_name)
        return configdir

    def get_home_dir(self):
        if sys.platform == "cygwin":
            home_dir = os.getenv('HOME')
        else:
            home_dir = os.getenv('USERPROFILE') or os.getenv('HOME')
        if home_dir is not None:
            return os.path.normpath(home_dir)
        else:
            raise KeyError("Neither USERPROFILE or HOME environment variables set.")

The get_desktop_environment method has been posted in another thread . get_desktop_environment 方法已在另一个线程中发布。

On a gnome desktop, you usually do this with gconf, either directly calling gconftool or using the gconf python module.在 gnome 桌面上,您通常使用 gconf 执行此操作,或者直接调用 gconftool 或使用 gconf python 模块。 The latter is in the link given by unutbu.后者在 unutbu 给出的链接中。 The first method could be done like this.第一种方法可以这样做。

import commands
command = "gconftool-2 --set /desktop/gnome/background/picture_filename --type string '/path/to/file.jpg'"
status, output = commands.getstatusoutput(command)  # status=0 if success

In gnome, it is probably preferable to use the python binding of gconf directly:在 gnome 中,最好直接使用 gconf 的 python 绑定:

import gconf
conf = gconf.client_get_default()
conf.set_string('/desktop/gnome/background/picture_filename','/path/to/filename.jpg')

On windows, you will need some trickery with pywin32 , andthe windows API , on 'linux' the answer will depend on which desktop is running - KDE, Gnome, or something more exotic.在 Windows 上,您需要使用pywin32windows API进行一些技巧,在“linux”上,答案将取决于正在运行的桌面 - KDE、Gnome 或其他更奇特的东西。 Under KDE (and maybe Gnome) you can probably send a message using D-Bus, which you could do without including any new libraries by using the command line tool dbus-send.在 KDE(也可能是 Gnome)下,您可能可以使用 D-Bus 发送消息,而无需使用命令行工具 dbus-send 就可以做到这一点。

The other option would be to set the desktop wallpaper to a file which you then edit / replace from python - but this will probably only result in a change when the user logs in.另一种选择是将桌面壁纸设置为一个文件,然后您可以从 python 编辑/替换该文件 - 但这可能只会在用户登录时导致更改。

Firstly, import ctypes : it gives you access to windows components such as the screensaver, wallpapers, etc.首先,导入ctypes :它使您可以访问 Windows 组件,例如屏幕保护程序、壁纸等。

Then call然后打电话

ctypes.windll.user32.SystemParametersInfoA(20, 0, the_complete_path_of_your_image, 0)

Make sure the path is the complete path of your image, not just the path from the active directory确保路径是图像的完整路径, 而不仅仅是来自活动目录的路径

There is a difference what SystemParametersInfo method to be called based on what if you are running on 64 bit or 32 bit OS.根据您在 64 位或 32 位操作系统上运行的情况,要调用的SystemParametersInfo方法有所不同。 For 64 bit you have to use SystemParametersInfoW (Unicode) and for 32 bit SystemParametersInfoA (ANSI)对于 64 位,您必须使用 SystemParametersInfoW (Unicode) 和 32 位 SystemParametersInfoA (ANSI)

import struct
import ctypes


SPI_SETDESKWALLPAPER = 20
WALLPAPER_PATH = 'C:\\your_file_name.jpg'


def is_64_windows():
    """Find out how many bits is OS. """
    return struct.calcsize('P') * 8 == 64


def get_sys_parameters_info():
    """Based on if this is 32bit or 64bit returns correct version of SystemParametersInfo function. """
    return ctypes.windll.user32.SystemParametersInfoW if is_64_windows() \
        else ctypes.windll.user32.SystemParametersInfoA


def change_wallpaper():
    sys_parameters_info = get_sys_parameters_info()
    r = sys_parameters_info(SPI_SETDESKWALLPAPER, 0, WALLPAPER_PATH, 3)

    # When the SPI_SETDESKWALLPAPER flag is used,
    # SystemParametersInfo returns TRUE
    # unless there is an error (like when the specified file doesn't exist).
    if not r:
        print(ctypes.WinError())


change_wallpaper()
import ctypes,win32con

def getWallpaper():
    ubuf = ctypes.create_unicode_buffer(512)
    ctypes.windll.user32.SystemParametersInfoW(win32con.SPI_GETDESKWALLPAPER,len(ubuf),ubuf,0)
    return ubuf.value

def setWallpaper(path):
    changed = win32con.SPIF_UPDATEINIFILE | win32con.SPIF_SENDCHANGE
    ctypes.windll.user32.SystemParametersInfoW(win32con.SPI_SETDESKWALLPAPER,0,path,changed)

Alternatively: (with SystemParametersInfoA )或者:(使用SystemParametersInfoA

def getWallpaper():
    sbuf = ctypes.create_string_buffer(512) # ctypes.c_buffer(512)
    ctypes.windll.user32.SystemParametersInfoA(win32con.SPI_GETDESKWALLPAPER,len(sbuf),sbuf,0)
    return sbuf.value

def setWallpaper(path):
    changed = win32con.SPIF_UPDATEINIFILE | win32con.SPIF_SENDCHANGE
    ctypes.windll.user32.SystemParametersInfoA(win32con.SPI_SETDESKWALLPAPER,0,path.encode(),changed) # "".encode() = b""

Arguments are:论据是:
SystemParametersInfo(SetOrGet, GetBufferSize, SetBufferOrGetBuffer, SetChange)

The path has to be absolute, so if you're using something relative to your script, do:路径必须是绝对的,因此如果您使用与脚本相关的内容,请执行以下操作:
path = os.path.abspath(path)

To see more stuff you can do with SystemParametersInfo , see the docs .要查看您可以使用SystemParametersInfo执行的更多操作,请参阅文档
(near the bottom there's an example to change the mouse speed) (靠近底部有一个改变鼠标速度的例子)

PS There are many answers already here, but they're leaving out the broadcasting you're supposed to do. PS这里已经有很多答案,但他们忽略了你应该做的广播。 Sure it works without it, but it's bad practice not to use it properly.当然没有它也可以工作,但不正确使用它是不好的做法。

PPS And they only gave hard coded values, rather than the variables they come from. PPS 而且他们只给出了硬编码的值,而不是它们来自的变量。

Also note, i use 512 characters for the buffer size when getting the path, just to be more safe since paths might exceed 256. I doubt anyone will have paths as long as that though.另请注意,我在获取路径时使用 512 个字符作为缓冲区大小,只是为了更安全,因为路径可能超过 256。我怀疑任何人都会有这么长的路径。

One more note.再来一注。 I've only tested the above examples in Python 3, but i don't think SystemParametersInfoA needs the .encode() in Python 2. (they updated strings in Python 3 to unicode i believe) The string in SystemParametersInfoW may need converting for Python 2.我只在 Python 3 中测试了上述示例,但我认为 SystemParametersInfoA 不需要 Python 2 中的 .encode() 。(我相信他们将 Python 3 中的字符串更新为 unicode) SystemParametersInfoW 中的字符串可能需要为 Python 转换2.

I read all the answers and after searching for a while i found a easier solution.我阅读了所有答案,经过一段时间的搜索,我找到了一个更简单的解决方案。

Install the module named py-wallpaper.安装名为 py-wallpaper 的模块。

pip install py-wallpaper

Import the module.导入模块。

from wallpaper import set_wallpaper, get_wallpaper

set the wallpaper using set walpaper使用 set walpaper 设置壁纸

set_wallpaper("location/to/image.jpg")

get the current wallpaper's path using get wallpaper使用获取壁纸获取当前壁纸的路径

print(get_wallpaper())

thanks.谢谢。

changing the background image of desktop更改桌面的背景图像

    import ctypes
    import os
    SPI_SETDESKWALLPAPER = 20 
    ctypes.windll.user32.SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, 'your image path', 3) 
    #'C:\\Users\\Public\\Pictures\\abc.jpg'

it worked fine for me.它对我来说很好。 windows10, python27 windows10、p​​ython27

On Windows with python2.5 or higher, use ctypes to load user32.dll and call在具有 python2.5 或更高版本的 Windows 上,使用 ctypes 加载 user32.dll 并调用

import ctypes
ctypes.windll.user32.SystemParametersInfoW(20,0,"Path_wallpaper", 0) 
     speak("Background changed succesfully")

Just adding a small precision to ShivaGuntuku 's post : In python 3 you should replace the 'A' by a 'W' in SytemParametersInfoA.只需在 ShivaGuntuku 的帖子中添加一个小精度:在 python 3 中,您应该在 SytemParametersInfoA 中将“A”替换为“W”。 Small exemple to change your desktop background in windows10 with python 3 :使用 python 3 在 windows10 中更改桌面背景的小示例:

import ctypes
import os
SPI_SETDESKWALLPAPER = 20
ctypes.windll.user32.SystemParametersInfoW(
    SPI_SETDESKWALLPAPER, 0, 'C:\\Users\\godet\\OneDrive\\Images\\breaker_wall.jpg', 0)

this works for me这对我有用

import ctypes
ctypes.windll.user32.SystemParametersInfoW(20,0,path:os.PathLike,3)

You can use this library PyWallpaper , worked for me on mac also.你可以使用这个库PyWallpaper ,它也在 mac 上为我工作。

To install type pip install PyWallpaper .要安装类型pip install PyWallpaper And then to change/set your wallpaper -然后更改/设置您的墙纸 -

from PyWallpaper import change_wallpaper
change_wallpaper("/some_path/sample.jpg")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM