Reputation: 2399
I'd like a code snippet that gets the proper directory for app data (config files, etc) on all platforms (Win/Mac/Linux at least). For example: %APPDATA%/ on Windows.
Upvotes: 33
Views: 15162
Reputation: 1056
The platformdirs package serves that purpose. For example, platformdirs.user_cache_dir
.
Upvotes: 0
Reputation: 519
You can use the following function to get user data dir, tested in linux and w10 (returning AppData/Local
dir) it's adapted from the appdirs package:
import sys
from pathlib import Path
from os import getenv
def get_user_data_dir(appname: str) -> Path:
if sys.platform == "win32":
import winreg
key = winreg.OpenKey(
winreg.HKEY_CURRENT_USER,
r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders",
)
dir_, _ = winreg.QueryValueEx(key, "Local AppData")
ans = Path(dir_).resolve(strict=False)
elif sys.platform == "darwin":
ans = Path("~/Library/Application Support/").expanduser()
else:
ans = Path(getenv("XDG_DATA_HOME", "~/.local/share")).expanduser()
return ans.joinpath(appname)
Upvotes: 3
Reputation: 101
If you are after the config directory here is a solution that defaults to ~/.config
unless a platform specific (sys.platform
) entry is available in the method's local platforms: dict
from sys import platform
from os.path import expandvars, join
def platform_config_directory() -> str:
'''
Platform config directory
Entries available in local platforms dict use the current
"best practice" location for config directories.
Default: $HOME/.config (XDG Base Directory Specification)
https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
'''
home: str = expandvars('$HOME')
platforms: dict = {
"win32": expandvars('%AppData%'),
"darwin": join(home, 'Library', 'Application Support'),
}
if platform in platforms:
return platforms[platform]
return join(home, '.config')
This works on windows, mac and linux, however allows for easier expansion given the need.
Upvotes: 0
Reputation: 189656
If you don't mind using the appdirs module, it should solve your problem. (cost = you either need to install the module or include it directly in your Python application.)
Upvotes: 19
Reputation: 2585
You can use module called appdata:
pip install appdata
from appdata import AppDataPaths
app_paths = AppDataPaths()
app_paths.app_data_path # cross-platform path to AppData folder
Upvotes: 1
Reputation: 47
I came across a similar problem and I wanted to dynamically resolve all of the Windows % paths without knowing about them prior. You can use os.path.expandvars
to resolve the paths dynamically. Something like this:
from os import path
appdatapath = '%APPDATA%\MyApp'
if '%' in appdatapath:
appdatapath = path.expandvars(appdatapath)
print(appdatapath)
The line at the end will print: C:\Users\\{user}\AppData\Roaming\MyApp
This works for windows however I have not tested on Linux. So long as the paths are defined by the environment than expandvars should be able to find it. You can read more about expand vars here.
Upvotes: 1
Reputation: 8758
Qt's QStandardPaths documentation lists paths like this.
Using Python 3.8
import sys
import pathlib
def get_datadir() -> pathlib.Path:
"""
Returns a parent directory path
where persistent application data can be stored.
# linux: ~/.local/share
# macOS: ~/Library/Application Support
# windows: C:/Users/<USER>/AppData/Roaming
"""
home = pathlib.Path.home()
if sys.platform == "win32":
return home / "AppData/Roaming"
elif sys.platform == "linux":
return home / ".local/share"
elif sys.platform == "darwin":
return home / "Library/Application Support"
# create your program's directory
my_datadir = get_datadir() / "program-name"
try:
my_datadir.mkdir(parents=True)
except FileExistsError:
pass
The Python documentation recommends the sys.platform.startswith('linux')
"idiom" for compatibility with older versions of Python that returned things like "linux2" or "linux3".
Upvotes: 17
Reputation: 57
I recommend researching the locations of 'appdata' in the operating systems that you want to use this program on. Once you know the locations you could simple use if statements to detect the os and do_something().
import sys
if sys.platform == "platform_value":
do_something()
elif sys.platform == "platform_value":
do_something()
List is from the official Python docs. (Search for 'sys.platform')
Upvotes: 1