How can I change my desktop background with python?
如何使用python更改桌面背景?
I want to do it in both Windows and Linux.
我想在Windows和Linux中都这样做。
9 个解决方案
#1
10
On a gnome desktop, you usually do this with gconf, either directly calling gconftool or using the gconf python module. The latter is in the link given by unutbu. The first method could be done like this.
在gnome桌面上,通常使用gconf执行此操作,直接调用gconftool或使用gconf python模块。后者是unutbu给出的链接。第一种方法可以像这样完成。
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
#2
32
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)
#3
12
For Python3.5, SystemParametersInfoA doesn't work. Use SystemParametersInfoW.
对于Python3.5,SystemParametersInfoA不起作用。使用SystemParametersInfoW。
import ctypes
ctypes.windll.user32.SystemParametersInfoW(20, 0, "absolute path" , 0)
#4
9
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://*.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://*.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方法已发布在另一个线程中。
#5
6
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')
#6
3
On windows, you will need some trickery with pywin32, and the windows API, on 'linux' the answer will depend on which desktop is running - KDE, Gnome, or something more exotic. 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.
在Windows上,你需要一些技巧与pywin32,以及windows API,在'linux'上答案将取决于运行的桌面 - KDE,Gnome或更具异国情调的东西。在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中编辑/替换 - 但这可能只会在用户登录时导致更改。
#7
3
Firstly, import ctypes
: it gives you access to windows components such as the screensaver, wallpapers, etc.
首先,导入ctypes:它允许您访问Windows组件,如屏幕保护程序,壁纸等。
Then call ctypes.windll.user32.SystemParametersInfoA(a,b,c,d)
:
然后调用ctypes.windll.user32.SystemParametersInfoA(a,b,c,d):
a
= 20
a = 20
b
= 0
b = 0
c
= The COMPLETE path of the image. Not just the path from the active directory
c =图像的COMPLETE路径。不只是来自活动目录的路径
d
= 0
d = 0
#8
2
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,python27
#9
2
There is a difference what SystemParametersInfo method to be called based on what if you are running on 64 bit or 32 bit OS. For 64 bit you have to use SystemParametersInfoW (Unicode) and for 32 bit SystemParametersInfoA (ANSI)
根据您在64位或32位操作系统上运行的内容,调用SystemParametersInfo方法有所不同。对于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()
#1
10
On a gnome desktop, you usually do this with gconf, either directly calling gconftool or using the gconf python module. The latter is in the link given by unutbu. The first method could be done like this.
在gnome桌面上,通常使用gconf执行此操作,直接调用gconftool或使用gconf python模块。后者是unutbu给出的链接。第一种方法可以像这样完成。
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
#2
32
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)
#3
12
For Python3.5, SystemParametersInfoA doesn't work. Use SystemParametersInfoW.
对于Python3.5,SystemParametersInfoA不起作用。使用SystemParametersInfoW。
import ctypes
ctypes.windll.user32.SystemParametersInfoW(20, 0, "absolute path" , 0)
#4
9
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://*.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://*.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方法已发布在另一个线程中。
#5
6
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')
#6
3
On windows, you will need some trickery with pywin32, and the windows API, on 'linux' the answer will depend on which desktop is running - KDE, Gnome, or something more exotic. 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.
在Windows上,你需要一些技巧与pywin32,以及windows API,在'linux'上答案将取决于运行的桌面 - KDE,Gnome或更具异国情调的东西。在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中编辑/替换 - 但这可能只会在用户登录时导致更改。
#7
3
Firstly, import ctypes
: it gives you access to windows components such as the screensaver, wallpapers, etc.
首先,导入ctypes:它允许您访问Windows组件,如屏幕保护程序,壁纸等。
Then call ctypes.windll.user32.SystemParametersInfoA(a,b,c,d)
:
然后调用ctypes.windll.user32.SystemParametersInfoA(a,b,c,d):
a
= 20
a = 20
b
= 0
b = 0
c
= The COMPLETE path of the image. Not just the path from the active directory
c =图像的COMPLETE路径。不只是来自活动目录的路径
d
= 0
d = 0
#8
2
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,python27
#9
2
There is a difference what SystemParametersInfo method to be called based on what if you are running on 64 bit or 32 bit OS. For 64 bit you have to use SystemParametersInfoW (Unicode) and for 32 bit SystemParametersInfoA (ANSI)
根据您在64位或32位操作系统上运行的内容,调用SystemParametersInfo方法有所不同。对于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()