on windows to get the path of the Downloads
folder, it should be done through win32Api, specifically through SHGetKnownFolderPath, python has access to it through ctypes, the way to access this specific function is taken from Windows Special and Known Folders from python stack overflow answer. with some modifications to read c_wchar_p.
you have to pass in the GUID for the downloads folder from KNOWNFOLDERID which is "{374DE290-123F-4565-9164-39C4925E467B}"
.
, so you end up with the following code that works only on 64-bit python, for 32-bit you will probably have to change the argument types.
from ctypes import windll, wintypes
from ctypes import *
from uuid import UUID
from itertools import count
from functools import partial
# ctypes GUID copied from MSDN sample code
class GUID(Structure):
_fields_ = [
("Data1", wintypes.DWORD),
("Data2", wintypes.WORD),
("Data3", wintypes.WORD),
("Data4", wintypes.BYTE * 8)
]
def __init__(self, uuidstr):
uuid = UUID(uuidstr)
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
FOLDERID_Downloads = '{374DE290-123F-4565-9164-39C4925E467B}'
SHGetKnownFolderPath = windll.shell32.SHGetKnownFolderPath
SHGetKnownFolderPath.argtypes = [
POINTER(GUID), wintypes.DWORD, wintypes.HANDLE, POINTER(c_char_p)]
def get_known_folder_path(uuidstr):
pathptr = c_char_p()
guid = GUID(uuidstr)
if SHGetKnownFolderPath(byref(guid), 0, 0, byref(pathptr)):
raise Exception('Whatever you want here...')
resp = cast(pathptr,POINTER(c_wchar))
iterator = (resp.__getitem__(i) for i in count(0))
result = ''.join(list(iter(iterator.__next__, '\x00')))
return result
print(get_known_folder_path(FOLDERID_Downloads))
this will return the Downloads folder location even if the user changes it through the properties, or for different languages.
on linux a similar method is to get it from $HOME/.config/user-dirs.dirs
under the name of XDG_DOWNLOAD_DIR
, which is changed with user settings changes.
$ grep XDG_DOWNLOAD_DIR ~/.config/user-dirs.dirs
XDG_DOWNLOAD_DIR="$HOME/Downloads"
This is obviously only the "default" location, you should allow the user to manually specify his own custom downloads path.
Using a hardcoded path is a recipe for "but it works on my machine", so just ask the OS about its path.