This question already has answers here:
How to get Desktop location?
(9 answers)
Closed 6 months ago.
I am new to the os library and I was wondering how I could find the path for any user who uses windows and access their desktop directory using python. Thanks in advance!
You can do it by using os.environ mapping and add the Desktop path
import os
print(os.environ['USERPROFILE'] + '\Desktop')
Previous solutions won't work if the Desktop folder was manually changed by the user (to a OneDrive folder or whatever...).
This will work:
from win32com.shell import shell, shellcon
desktop = shell.SHGetFolderPath (0, shellcon.CSIDL_DESKTOP, 0, 0)
You can also try to query the registry.
import subprocess
import sys
import os
if sys.platform == "win32":
command = r'reg query "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "Desktop"'
result = subprocess.run(command, stdout=subprocess.PIPE, text = True)
desktop = result.stdout.splitlines()[2].split()[2]
else:
desktop = os.path.expanduser("~/Desktop")
print(desktop)
#D:\Desktop
Related
I have a python file, which is... supposed to be an app. I found out that if I put a shortcut of it in the
"C:\Users\xxxxxxxxx\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\System Tools"
section, that I would be able to put it in the application list, and the system would detect is as an app.
The python file will be a game kind of thing, and if others install it, it would be better if there was just another python file that creates the shortcut in the destination.
But.
I do not know how to do this with python.
I tried this:
import win32com.client
import getpass
from time import sleep
user = getpass.getuser()
import pythoncom
import os
# pythoncom.CoInitialize() # remove the '#' at the beginning of the line if
running in a thread.
desktop = r'C:/Users/' + user + '/AppData/Roaming/Microsoft/Windows/Start
Menu/Programs/System Tools' # path to where you want to put the .lnk
path = os.path.join(desktop, 'Skulk.lnk')
target = r'C:/Users/' + user + '/main.py'
shell = win32com.client.Dispatch("WScript.Shell")
shortcut = shell.CreateShortCut(path)
shortcut.Targetpath = target
shortcut.WindowStyle = 7 # 7 - Minimized, 3 - Maximized, 1 - Normal
shortcut.save()
print("Success!")
sleep(3)
If it is, could you please tell me how to do it?
Any help would be greatly appreciated.
I am using this code to obtain current window
from typing import Optional
from ctypes import wintypes, windll, create_unicode_buffer
def getForegroundWindowTitle() -> Optional[str]:
hWnd = windll.user32.GetForegroundWindow()
length = windll.user32.GetWindowTextLengthW(hWnd)
buf = create_unicode_buffer(length + 1)
windll.user32.GetWindowTextW(hWnd, buf, length + 1)
return buf.value if buf.value else None
print(getForegroundWindowTitle())
output:
Videos
git
Downloads
Python check if current window is file explorer - Stack Overflow - Google Chrome
While google chrome tabs can be easily identified using this, problem is there's no way to know whether Videos, git, Downloads are windows folder (opened using file explorer).
So, is there a way to get the output in this format Videos - File Explorer ?
/ check whether the current window is a windows folder/file explorer window ?
From the same Question I modified the Code of Nuno Andre
https://stackoverflow.com/a/56572696/2532695
import ctypes
from ctypes import wintypes
import psutil
user32 = ctypes.windll.user32
h_wnd = user32.GetForegroundWindow()
pid = wintypes.DWORD()
user32.GetWindowThreadProcessId(h_wnd, ctypes.byref(pid))
print(psutil.Process(pid.value).name())
This one should do the trick, but you need psutil (pip install psutil).
You should see something like "Explorer.exe" if the active Window is an Explorer-Window.
I already found this question that suggests to use os.path.expanduser(path) to get the user's home directory.
I would like to achieve the same with the "Downloads" folder. I know that this is possible in C#, yet I'm new to Python and don't know if this is possible here too, preferable platform-independent (Windows, Ubuntu).
I know that I just could do download_folder = os.path.expanduser("~")+"/Downloads/", yet (at least in Windows) it is possible to change the Default download folder.
from pathlib import Path
downloads_path = str(Path.home() / "Downloads")
This fairly simple solution (expanded from this reddit post) worked for me
import os
def get_download_path():
"""Returns the default downloads path for linux or windows"""
if os.name == 'nt':
import winreg
sub_key = r'SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders'
downloads_guid = '{374DE290-123F-4565-9164-39C4925E467B}'
with winreg.OpenKey(winreg.HKEY_CURRENT_USER, sub_key) as key:
location = winreg.QueryValueEx(key, downloads_guid)[0]
return location
else:
return os.path.join(os.path.expanduser('~'), 'downloads')
The GUID can be obtained from Microsoft's KNOWNFOLDERID docs
This can be expanded to work more generically other directories
For python3+ mac or linux
from pathlib import Path
path_to_download_folder = str(os.path.join(Path.home(), "Downloads"))
Correctly locating Windows folders is somewhat of a chore in Python. According to answers covering Microsoft development technologies, such as this one, they should be obtained using the Vista Known Folder API. This API is not wrapped by the Python standard library (though there is an issue from 2008 requesting it), but one can use the ctypes module to access it anyway.
Adapting the above answer to use the folder id for downloads shown here and combining it with your existing Unix code should result in code that looks like this:
import os
if os.name == 'nt':
import ctypes
from ctypes import windll, wintypes
from uuid import UUID
# ctypes GUID copied from MSDN sample code
class GUID(ctypes.Structure):
_fields_ = [
("Data1", wintypes.DWORD),
("Data2", wintypes.WORD),
("Data3", wintypes.WORD),
("Data4", wintypes.BYTE * 8)
]
def __init__(self, uuidstr):
uuid = UUID(uuidstr)
ctypes.Structure.__init__(self)
self.Data1, self.Data2, self.Data3, \
self.Data4[0], self.Data4[1], rest = uuid.fields
for i in range(2, 8):
self.Data4[i] = rest>>(8-i-1)*8 & 0xff
SHGetKnownFolderPath = windll.shell32.SHGetKnownFolderPath
SHGetKnownFolderPath.argtypes = [
ctypes.POINTER(GUID), wintypes.DWORD,
wintypes.HANDLE, ctypes.POINTER(ctypes.c_wchar_p)
]
def _get_known_folder_path(uuidstr):
pathptr = ctypes.c_wchar_p()
guid = GUID(uuidstr)
if SHGetKnownFolderPath(ctypes.byref(guid), 0, 0, ctypes.byref(pathptr)):
raise ctypes.WinError()
return pathptr.value
FOLDERID_Download = '{374DE290-123F-4565-9164-39C4925E467B}'
def get_download_folder():
return _get_known_folder_path(FOLDERID_Download)
else:
def get_download_folder():
home = os.path.expanduser("~")
return os.path.join(home, "Downloads")
A more complete module for retrieving known folders from Python is available on github.
Some linux distributions localize the name of the Downloads folder. E.g. after changing my locale to zh_TW, the Downloads folder became /home/user/下載. The correct way on linux distributions (using xdg-utils from freedesktop.org) is to call xdg-user-dir:
import subprocess
# Copy windows part from other answers here
try:
folder = subprocess.run(["xdg-user-dir", "DOWNLOAD"],
capture_output=True, text=True).stdout.strip("\n")
except FileNotFoundError: # if the command is missing
import os.path
folder = os.path.expanduser("~/Downloads") # fallback
Note that the use of capture_output requires Python ≥3.7.
If you already use GLib or don't mind adding more dependencies, see also
these approaches using packages.
For python3 on windows try:
import os
folder = os.path.join(os.path.join(os.environ['USERPROFILE']), 'folder_name')
print(folder)
I want to create a start menu or Desktop shortcut for my Python windows installer package. I am trying to follow https://docs.python.org/3.4/distutils/builtdist.html#the-postinstallation-script
Here is my script;
import sys
from os.path import dirname, join, expanduser
pyw_executable = sys.executable.replace('python.exe','pythonw.exe')
script_file = join(dirname(pyw_executable), 'Scripts', 'tklsystem-script.py')
w_dir = expanduser(join('~','lsf_files'))
print(sys.argv)
if sys.argv[1] == '-install':
print('Creating Shortcut')
create_shortcut(
target=pyw_executable,
description='A program to work with L-System Equations',
filename='L-System Tool',
arguments=script_file,
workdir=wdir
)
I also specified this script in scripts setup option, as indicated by aforementioned docs.
Here is the command I use to create my installer;
python setup.py bdist_wininst --install-script tklsystem-post-install.py
After I install my package using created windows installer, I can't find where my shorcut is created, nor I can confirm whether my script run or not?
How can I make setuptools generated windows installer to create desktop or start menu shortcuts?
Like others have commented here and elsewhere the support functions don't seem to work at all (at least not with setuptools). After a good day's worth of searching through various resources I found a way to create at least the Desktop shortcut. I'm sharing my solution (basically an amalgam of code I found here and here). I should add that my case is slightly different from yasar's, because it creates a shortcut to an installed package (i.e. an .exe file in Python's Scripts directory) instead of a script.
In short, I added a post_install function to my setup.py, and then used the Python extensions for Windows to create the shortcut. The location of the Desktop folder is read from the Windows registry (there are other methods for this, but they can be unreliable if the Desktop is at a non-standard location).
#!/usr/bin/env python
import os
import sys
import sysconfig
if sys.platform == 'win32':
from win32com.client import Dispatch
import winreg
def get_reg(name,path):
# Read variable from Windows Registry
# From https://stackoverflow.com/a/35286642
try:
registry_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, path, 0,
winreg.KEY_READ)
value, regtype = winreg.QueryValueEx(registry_key, name)
winreg.CloseKey(registry_key)
return value
except WindowsError:
return None
def post_install():
# Creates a Desktop shortcut to the installed software
# Package name
packageName = 'mypackage'
# Scripts directory (location of launcher script)
scriptsDir = sysconfig.get_path('scripts')
# Target of shortcut
target = os.path.join(scriptsDir, packageName + '.exe')
# Name of link file
linkName = packageName + '.lnk'
# Read location of Windows desktop folder from registry
regName = 'Desktop'
regPath = r'Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders'
desktopFolder = os.path.normpath(get_reg(regName,regPath))
# Path to location of link file
pathLink = os.path.join(desktopFolder, linkName)
shell = Dispatch('WScript.Shell')
shortcut = shell.CreateShortCut(pathLink)
shortcut.Targetpath = target
shortcut.WorkingDirectory = scriptsDir
shortcut.IconLocation = target
shortcut.save()
setup(name='mypackage',
...,
...)
if sys.argv[1] == 'install' and sys.platform == 'win32':
post_install()
Here's a link to a full setup script in which I used this:
https://github.com/KBNLresearch/iromlab/blob/master/setup.py
If you want to confirm whether the script is running or not, you can print to a file instead of the console. Looks like text you print to console in the post-install script won't show up.
Try this:
import sys
from os.path import expanduser, join
pyw_executable = join(sys.prefix, "pythonw.exe")
shortcut_filename = "L-System Toolsss.lnk"
working_dir = expanduser(join('~','lsf_files'))
script_path = join(sys.prefix, "Scripts", "tklsystem-script.py")
if sys.argv[1] == '-install':
# Log output to a file (for test)
f = open(r"C:\test.txt",'w')
print('Creating Shortcut', file=f)
# Get paths to the desktop and start menu
desktop_path = get_special_folder_path("CSIDL_COMMON_DESKTOPDIRECTORY")
startmenu_path = get_special_folder_path("CSIDL_COMMON_STARTMENU")
# Create shortcuts.
for path in [desktop_path, startmenu_path]:
create_shortcut(pyw_executable,
"A program to work with L-System Equations",
join(path, shortcut_filename),
script_path,
working_dir)
At least with Python 3.6.5, 32bit on Windows, setuptools does work for this. But based on the accepted answer, by trial and error I found some issues that may have caused your script to fail to do what you wanted.
create_shortcut does not accept keyword arguments, only positional, so its usage in your code is invalid
You must add a .lnk extension for Windows to recognise the shortcut
I found sys.executable will be the name of the installer executable, not the python executable
As mentioned, you can't see stdout or stderr so you might want to log to a text file. I would suggest also redirecting sys.stdout and sys.stderr to the log file.
(Maybe not relevant) as mentioned in this question there appears to be a bug with the version string generated by bdist_wininst. I used the hexediting hack from an answer there to work around this. The location in the answer is not the same, you have to find the -32 yourself.
Full example script:
import sys
import os
import datetime
global datadir
datadir = os.path.join(get_special_folder_path("CSIDL_APPDATA"), "mymodule")
def main(argv):
if "-install" in argv:
desktop = get_special_folder_path("CSIDL_DESKTOPDIRECTORY")
print("Desktop path: %s" % repr(desktop))
if not os.path.exists(datadir):
os.makedirs(datadir)
dir_created(datadir)
print("Created data directory: %s" % repr(datadir))
else:
print("Data directory already existed at %s" % repr(datadir))
shortcut = os.path.join(desktop, "MyModule.lnk")
if os.path.exists(shortcut):
print("Remove existing shortcut at %s" % repr(shortcut))
os.unlink(shortcut)
print("Creating shortcut at %s...\n" % shortcut)
create_shortcut(
r'C:\Python36\python.exe',
"MyModuleScript",
shortcut,
"",
datadir)
file_created(shortcut)
print("Successfull!")
elif "-remove" in sys.argv:
print("Removing...")
pass
if __name__ == "__main__":
logfile = r'C:\mymodule_install.log' # Fallback location
if os.path.exists(datadir):
logfile = os.path.join(datadir, "install.log")
elif os.environ.get("TEMP") and os.path.exists(os.environ.get("TEMP"),""):
logfile = os.path.join(os.environ.get("TEMP"), "mymodule_install.log")
with open(logfile, 'a+') as f:
f.write("Opened\r\n")
f.write("Ran %s %s at %s" % (sys.executable, " ".join(sys.argv), datetime.datetime.now().isoformat()))
sys.stdout = f
sys.stderr = f
try:
main(sys.argv)
except Exception as e:
raise
f.close()
sys.exit(0)
UPD: on an off chance that the client machine has pywin32 installed, we try in-process creation first. Somewhat cleaner that way.
Here is another take. This assumes the package is called myapp, and that also becomes the executable that you want a shortcut to. Substitute your own package name and your own shortcut text.
Uses a Windows Scripting Host COM class - in process if possible, inside a Powershell command line as a subprocess if not. Tested on Python 3.6+.
from setuptools import setup
from setuptools.command.install import install
import platform, sys, os, site
from os import path, environ
def create_shortcut_under(root, exepath):
# Root is an env variable name -
# either ALLUSERSPROFILE for the all users' Start menu,
# or APPDATA for the current user specific one
profile = environ[root]
linkpath = path.join(profile, "Microsoft", "Windows", "Start Menu", "Programs", "My Python app.lnk")
try:
from win32com.client import Dispatch
from pywintypes import com_error
try:
sh = Dispatch('WScript.Shell')
link = sh.CreateShortcut(linkpath)
link.TargetPath = exepath
link.Save()
return True
except com_error:
return False
except ImportError:
import subprocess
s = "$s=(New-Object -COM WScript.Shell).CreateShortcut('" + linkpath + "');$s.TargetPath='" + exepath + "';$s.Save()"
return subprocess.call(['powershell', s], stdout = subprocess.DEVNULL, stderr = subprocess.DEVNULL) == 0
def create_shortcut(inst):
try:
exepath = path.join(path.dirname(sys.executable), "Scripts", "myapp.exe")
if not path.exists(exepath):
# Support for "pip install --user"
exepath = path.join(path.dirname(site.getusersitepackages()), "Scripts", "myapp.exe")
# If can't modify the global menu, fall back to the
# current user's one
if not create_shortcut_under('ALLUSERSPROFILE', exepath):
create_shortcut_under('APPDATA', exepath)
except:
pass
class my_install(install):
def run(self):
install.run(self)
if platform.system() == 'Windows':
create_shortcut(self)
#...
setup(
#...
cmdclass={'install': my_install},
entry_points={"gui_scripts": ["myapp = myapp.__main__:main"]},
I'm writing a PyGTK GUI application in Ubuntu to browse some images, and I'd like to open an image in the default image viewer application when it is double-clicked (like when it is opened in Nautilus).
How can I do it?
I don't know specifically using PyGTK but: xdg-open opens the default app for a file so running something like this should work:
import os
os.system('xdg-open ./img.jpg')
EDIT: I'd suggest using the subprocess module as in the comments. I'm not sure exactly how to use it yet so I just used os.system in the example to show xdg-open.
In GNU/Linux use xdg-open, in Mac use open, in Windows use start. Also, use subprocess, if not you risk to block your application when you call the external app.
This is my implementation, hope it helps: http://goo.gl/xebnV
import sys
import subprocess
import webbrowser
def default_open(something_to_open):
"""
Open given file with default user program.
"""
# Check if URL
if something_to_open.startswith('http') or something_to_open.endswith('.html'):
webbrowser.open(something_to_open)
return 0
ret_code = 0
if sys.platform.startswith('linux'):
ret_code = subprocess.call(['xdg-open', something_to_open])
elif sys.platform.startswith('darwin'):
ret_code = subprocess.call(['open', something_to_open])
elif sys.platform.startswith('win'):
ret_code = subprocess.call(['start', something_to_open], shell=True)
return ret_code
GTK (>= 2.14) has gtk_show_uri:
gtk.show_uri(screen, uri, timestamp)
Example usage:
gtk.show_uri(None, "file:///etc/passwd", gtk.gdk.CURRENT_TIME)
Related
How to open a file with the standard application?