FastAPI testing No ORM Databases - python

I am a None ORM user, I prefer to use plain text queries, I took that course on free code camp on FastAPI but almost the whole course revolves around ORMs so I struggle to implement a number of concepts found in that course.
My main struggle is when I write tests for my endpoints I need to use a test database rather than my development database, I am using testing.postgres to create the testing database and this is the code I am using :
client = TestClient(app)
class TestUser:
def setup_method(self, method):
self.postgres = testing.postgresql.Postgresql(cache_initialized_db=True)
self.db = psycopg2.connect(**self.postgres.dsn())
def teardown_method(self, method):
self.db.close()
def test_get_users(self):
res = client.get("/users")
assert res.status_code == 200
assert res.headers["content-type"] == "application/json"
my question is how to make my tests and cruds send queries to the test database, not the development database.
where is the link that I should add here?
Edit: this is the code I use for connection with database, I am not using a dependency for it :
while True:
try:
conn = psycopg2.connect(
database=settings.database,
user=settings.user,
port=settings.port,
password=settings.password,
cursor_factory=RealDictCursor,
)
cr = conn.cursor()
console.print(
"[green bold]SUCCESS[/]: Connection To Database Established successfuly"
)
break
except psycopg2.OperationalError:
console.print(
"[red bold]FAILED[/]: Connection To Database Failed , Trying Again"
)
time.sleep(2)
Edit2: this is the settings segment :
load_dotenv()
class Settings(BaseSettings):
database: str
user: str
port: int
password: str
expiray: int
algorithm: str
secret_key: str
settings = Settings()

If you wanna use the test database rather than the development database you should create the testing database and let the backend application be able to find the testing database and use it.

Kareem, I suggest you create your Settings instance from one or another .env file, based on an ENVIRONMENT variable:
import os
import sys
import pydantic
class Settings(pydantic.BaseSettings):
database: str
user: str
port: int
password: str
expiray: int
algorithm: str
secret_key: str
try:
ENVIRONMENT = os.environ['ENVIRONMENT']
except KeyError:
print('make sure to set an "ENVIRONMENT" env var')
sys.exit()
settings = Settings(_env_file=f'{ENVIRONMENT}.env', _env_file_encoding='utf-8')
This way, if you want to work with the testing database, you can do $ export ENVIRONMENT=test and it will load the settings from a file called test.env.
Does that make sense? Here are the docs for pydantic's dotenv support for BaseSettings subclasses.
As an aside, since you're interested in doing as much as you can without the use of an ORM and perhaps other dependencies, you really don't need pydantic for your purposes: You could simply change the above to something like:
import os
import sys
import types
import dotenv
try:
ENVIRONMENT = os.environ['ENVIRONMENT']
except KeyError:
print('make sure to set an "ENVIRONMENT" env var')
sys.exit()
db_settings_dict = dotenv.dotenv_values(f"{ENVIRONMENT}.env")
# to get dot notation as in your example
settings = types.SimpleNamespace(**db_settings_dict)
where test.env contains things like
database=hey.there.com:8768
user=kareem
...

Below is the Script I was written to control the ENV variable from the .env file, before running the unicorn server you would load the .env file based on the ENV mode to determine what kinds of modes are working on then use conditions to set up the corresponding DB path and name.
import os
import sys
from colored import fg
from os import environ, path
from dotenv import load_dotenv, set_key
import dotenv
def unknown(option, args=None):
color = fg('red')
if args:
print(color + f'Unknown arguments: -{args}')
else:
print(color + f'Unknown option: -{option}')
print("usage: python3 config.py [option] [arguments]")
print("Try `python3 config.py --help for more information")
color = fg('white')
print(color)
def version():
basedir = path.abspath(path.dirname(__file__))
load_dotenv(path.join(basedir, '.env'))
color = fg('blue')
print(color + '[VERSION]: ' + environ.get('VER'))
color = fg('white')
print(color)
def env():
basedir = path.abspath(path.dirname(__file__))
load_dotenv(path.join(basedir, '.env'))
color = fg('blue')
print(color + '[ENV]: ' + environ.get('ENV'))
color = fg('white')
print(color)
def set_env(env):
dotenv_file = dotenv.find_dotenv()
basedir = path.abspath(path.dirname(__file__))
load_dotenv(path.join(basedir, '.env'))
color = fg('blue')
print(color + f"[Updating ENV] ... ... from {environ.get('ENV')} to {env}")
os.environ["ENV"] = env
set_key(dotenv_file, 'ENV', os.environ['ENV'])
print("[Successfully Update the 'ENV' from .env]")
color = fg('white')
print(color)
def doc():
color = fg('blue')
print(color + "usage: python3 config.py [option] [arguments]")
read_me = """
-v : current project version
-env : current project environment
-set ENV={env} : set project env 'DEV' or 'PROD'
"""
print(read_me)
color = fg('white')
print(color)
def action_handler(option, args):
if option == '-set':
args_list = args.split('=')
if args_list[0] == 'ENV' and (args_list[1] == 'DEV' or args_list[1] == 'PROD'):
set_env(args_list[1])
else:
unknown(option=option, args=args)
else:
unknown(option=option)
argvs = len(sys.argv)
if argvs == 1:
doc()
elif argvs == 2:
option = sys.argv[1]
if option == '--help':
doc()
elif option == '-v':
version()
elif option == '-env':
env()
else:
unknown(option)
elif argvs == 3:
option, args = sys.argv[1], sys.argv[2]
action_handler(option, args)
else:
pass

Related

Finding the user's directory using python

So I am writing a script to automate some things that me and my teammates do. We have a git repo and this script is intended for all members to use. It has a part that is hardcoded to specifically be my folder path: C:/Users/jorge.padilla/etc...
I am still relatively new to python and not familiar with all the different libraries. I basically want to turn the user directory, i.e. jorge.padilla, into a variable that is not hardcoded, and that doesn't need to take user input so that the script will search for whatever the current user directory is and substitute it.
Below is a small snippet of the automation script I am writing to use as an example.
import os, sys
from pathlib import Path
from enum import Enum
#Global Variables
PRODUCTS_FOLDER = "Products"
APP_FOLDER = "App"
DEV_BUILD = "ionic cordova build android"
PROD_BUILD = "ionic cordova build android --release --prod"
class BuildConfig():
def __init__(self, start_path):
self.start_path = start_path
def getProductFolder(self):
return os.path.join(self.start_path, PRODUCTS_FOLDER)
class BuildTypeEnum(Enum):
PROD = 1
DEV = 2
def buildingApp(ConfigPath:BuildConfig, DEVvPROD:BuildTypeEnum):
path = ConfigPath.getProductFolder()
app_path = os.path.join(path, APP_FOLDER)
os.chdir(app_path)
if DEVvPROD == BuildTypeEnum.DEV:
os.system(DEV_BUILD)
elif DEVvPROD == BuildTypeEnum.PROD:
os.system(PROD_BUILD)
else:
print("Invalid input.")
return
if __name__ == "__main__":
root_start_path = "C:/Users/jorge.padilla/Documents/"
build = BuildConfig(root_start_path)
buildType = None
buildTypeInput = input("Is this a dev or production build? (d/p): ")
if (buildTypeInput.lower() == 'd'):
buildType = BuildTypeEnum.DEV
elif (buildTypeInput.lower() == 'p'):
buildType = BuildTypeEnum.PROD
else:
print("Please specify if this is a development or production build.")
return
The main variable I want to do this for is root_start_path
You should use pathlib (which you imported, but never used?):
import pathlib
root_start_path = pathlib.Path.home() # WindowsPath('C:/Users/jorge.padilla')
It works across platforms as well, and it's really the best way to handle file paths (IMO)
It can even simplify the syntax in accessing other directories within that path:
root_start_path = pathlib.Path.home() / 'Documents' # WindowsPath('C:/Users/jorge.padilla/Documents')
You could also do:
from os.path import expanduser
home = expanduser("~")

os.environ.get() does not return the Environment Value in windows?

I already set SLACK_TOKEN environment Variable. But "SLACK_TOKEN=os.environ.get('SLACK_TOKEN')" is returning "None".
The type of SLACK_TOKEN is NoneType. I think os.environ.get not fetching value of environment variable. so rest of the code is not executing.
import os
from slackclient import SlackClient
SLACK_TOKEN= os.environ.get('SLACK_TOKEN') #returning None
print(SLACK_TOKEN) # None
print(type(SLACK_TOKEN)) # NoneType class
slack_client = SlackClient(SLACK_TOKEN)
print(slack_client.api_call("api.test")) #{'ok': True}
print(slack_client.api_call("auth.test")) #{'ok': False, 'error': 'not_authed'}
def list_channels():
channels_call = slack_client.api_call("channels.list")
if channels_call['ok']:
return channels_call['channels']
return None
def channel_info(channel_id):
channel_info = slack_client.api_call("channels.info", channel=channel_id)
if channel_info:
return channel_info['channel']
return None
if __name__ == '__main__':
channels = list_channels()
if channels:
print("Channels: ")
for c in channels:
print(c['name'] + " (" + c['id'] + ")")
detailed_info = channel_info(c['id'])
if detailed_info:
print(detailed_info['latest']['text'])
else:
print("Unable to authenticate.") #Unable to authenticate
I faced similar issue.I fixed it by removing quotes from the values.
Example:
I created a local.env file wherein I stored my secret key values :
*local.env:*
export SLACK_TOKEN=xxxxxyyyyyyyzzzzzzz
*settings.py:*
SLACK_TOKEN = os.environ.get('SLACK_TOKEN')
In your python terminal or console,run the command : *source local.env*
****Involve local.env in gitignore.Make sure you dont push it to git as you have to safeguard your information.
This is applicable only to the local server.Hope this helps.Happy coding :)
In my case, I write wrong content in env file:
SLACK_TOKEN=xxxxxyyyyyyyzzzzzzz
I forgot export befor it, the correct should be:
export SLACK_TOKEN=xxxxxyyyyyyyzzzzzzz
You can use a config file to get the env vars without using export,
in the env file store varibale normally
.env:
DATABASE_URL=postgresql+asyncpg://postgres:dina#localhost/mysenseai
Then create a config file that will be used to store the env variable like so
config.py:
from pydantic import BaseSettings
class Settings(BaseSettings):
database_url: str
class Config:
env_file = '.env'
settings = Settings()
than you can use it that way
from config import settings
url = settings.database_url
If you declared the variable SLACK_TOKEN in the windows command prompt you will be able to access it in the same instance of that command prompt not anywhere including Powershell and the git bash. Be careful with that
whenever you want to run that python script, consider running it in the same command prompt where you declared those variables
you can always check if the variable exists in the cmd by running echo %SLACK_TOKEN% if it does not exists the cmd will return %SLACK_TOKEN%

How to parse PostgreSQL configuration file in python?

Python has ConfigParser library for parsing mysql configuration files.
https://docs.python.org/2/library/configparser.html
But i need to parse configuration files of PostgreSQL as well. But i couldn't find any parser for them.
In PostgreSQL there is no section or heading, so it can't be done by configparser.
Example:
# The default values of these variables are driven from the -D command-line
# option or PGDATA environment variable, represented here as ConfigDir.
data_directory = '/data/postgresql' # use data in another directory
# (change requires restart)
hba_file = '/etc/postgresql/9.1/main/pg_hba.conf' # host-based authentication file
# (change requires restart)
ident_file = '/etc/postgresql/9.1/main/pg_ident.conf' # ident configuration file
# (change requires restart)
# If external_pid_file is not explicitly set, no extra PID file is written.
external_pid_file = '/var/run/postgresql/9.1-main.pid' # write an extra PID file
# (change requires restart)
I was using the below code for mysql and it's working fine but not for postgresql.conf file.
import ConfigParser
class MysqlParserModule:
def __init__(self):
print 'Mysql Parser Module'
def parse_option(self, conf_file, section, option):
try:
config = ConfigParser.ConfigParser()
config.read(conf_file)
result = config.get(section, option)
print "'%s' value is '%s' under '%s' section" % (option, result, section)
except Exception as ex:
print 'in parse_option exception'
print ex
def test(self):
test = MysqlParserModule()
conf_file = '/root/Desktop/db_config/my_new.cnf'
section = 'client'
option = 'port'
test.parse_option(conf_file, section, option)
if __name__ == '__main__':
test = MysqlParserModule()
test.test()

Django best way to support developer specific config/settings

Here is the method my company devised, just wondering if anyone has anything better:
In Settings.py (at the bottom)
#...
try:
if socket.gethostname() == 'testsite':
from myir.local.TEST_settings import *
elif socket.gethostname() == 'prod':
from myir.local.PROD_settings import *
else:
from myir.local.DEV_settings import *
try:
# dev settings - don't commit local_settings.py
from proj.local.local_settings import *
except:
print "no local dev settings found..."
pass # intentionally do nothing.
except ImportError:
pass
local_settings.py:
DEBUG = True
LOGGING = { .. } # i usually keep maximum aount of logging possible in my dev environment.
... other configs you might want to override.
Django provides the environment variable DJANGO_SETTINGS_MODULE to specify the settings module to use. You can specify settings.my_prod_module there which enables settings to be different on production. Locally you can specify a different value.
You can also specify the value in your WSGI file:
os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings.my_prod_module'

How can I change my desktop background with python?

How can I change my desktop background with python?
I want to do it in both Windows and Linux.
On Windows with python2.5 or higher, use ctypes to load user32.dll and call SystemParametersInfo() with SPI_SETDESKWALLPAPER action.
For example:
import ctypes
SPI_SETDESKWALLPAPER = 20
ctypes.windll.user32.SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, "image.jpg" , 0)
For Python3.5, SystemParametersInfoA doesn't work. Use 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.
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.
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:
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, 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.
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.
Firstly, import ctypes: it gives you access to windows components such as the screensaver, wallpapers, etc.
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. For 64 bit you have to use SystemParametersInfoW (Unicode) and for 32 bit 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)
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.
(near the bottom there's an example to change the mouse speed)
P.S. There are many answers already here, but they're leaving out the broadcasting you're supposed to do. Sure it works without it, but it's bad practice not to use it properly.
P.P.S And they only gave hard coded values, rather than the variables they come from.
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.
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.
I read all the answers and after searching for a while i found a easier solution.
Install the module named py-wallpaper.
pip install py-wallpaper
Import the module.
from wallpaper import set_wallpaper, get_wallpaper
set the wallpaper using 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
On Windows with python2.5 or higher, use ctypes to load user32.dll and call
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. Small exemple to change your desktop background in windows10 with python 3 :
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.
To install type pip install PyWallpaper.
And then to change/set your wallpaper -
from PyWallpaper import change_wallpaper
change_wallpaper("/some_path/sample.jpg")

Categories