{"id":266,"library":"platformdirs","title":"platformdirs","description":"platformdirs is a Python library for determining platform-specific system directories — user data, config, cache, logs, runtime, and more. It is the actively maintained community fork of the now-deprecated appdirs package, implementing the XDG Base Directory Spec on Linux, ~/Library conventions on macOS, and AppData on Windows, with additional Android support. Current version is 4.9.4 (released 2026-03-05); the project releases frequently, with multiple minor/patch releases per month during active development periods.","status":"active","version":"4.9.4","language":"python","source_language":"en","source_url":"https://github.com/tox-dev/platformdirs","tags":["filesystem","cross-platform","xdg","appdirs","directories","pathlib","config","cache","data"],"install":[{"cmd":"pip install platformdirs","lang":"bash","label":"pip"}],"dependencies":[],"imports":[{"note":"appdirs is officially deprecated; PlatformDirs is the modern replacement. AppDirs is kept as an alias inside platformdirs for backward compatibility only.","wrong":"from appdirs import AppDirs","symbol":"PlatformDirs","correct":"from platformdirs import PlatformDirs"},{"note":"AppDirs is a legacy alias for PlatformDirs; prefer PlatformDirs for new code.","symbol":"AppDirs","correct":"from platformdirs import AppDirs"},{"note":"Functional API — returns str. Use the _path suffix variant (e.g. user_data_path) to get a pathlib.Path instead.","symbol":"user_data_dir","correct":"from platformdirs import user_data_dir"},{"note":"Returns pathlib.Path. Every _dir function has a corresponding _path variant.","symbol":"user_data_path","correct":"from platformdirs import user_data_path"},{"note":"Abstract base class; import for type annotations or custom subclassing only.","symbol":"PlatformDirsABC","correct":"from platformdirs import PlatformDirsABC"}],"quickstart":{"code":"from platformdirs import PlatformDirs, user_data_dir, user_config_path\n\n# OOP API — preferred for repeated access to multiple dirs\ndirs = PlatformDirs(appname=\"MyApp\", appauthor=\"MyCompany\", version=\"1.0\", ensure_exists=True)\nprint(dirs.user_data_dir)    # str: ~/.local/share/MyApp/1.0  (Linux)\nprint(dirs.user_config_dir)  # str: ~/.config/MyApp/1.0       (Linux)\nprint(dirs.user_cache_dir)   # str: ~/.cache/MyApp/1.0        (Linux)\nprint(dirs.user_log_dir)     # str: ~/.local/state/MyApp/1.0/log (Linux)\nprint(dirs.user_state_dir)   # str: ~/.local/state/MyApp/1.0  (Linux)\nprint(dirs.user_runtime_dir) # str: /run/user/<uid>/MyApp/1.0 (Linux)\n\n# _path variants return pathlib.Path objects\nprint(dirs.user_data_path)   # pathlib.Path\nprint(dirs.user_config_path) # pathlib.Path\n\n# Functional API — one-off lookups\nprint(user_data_dir(\"MyApp\", \"MyCompany\"))   # str\nprint(user_config_path(\"MyApp\", \"MyCompany\")) # pathlib.Path\n","lang":"python","description":"OOP API with ensure_exists, plus functional API demonstrating both str and Path return types."},"warnings":[{"fix":"After upgrading from <2.x or <3.x, migrate existing config files from the old path (~/Library/Preferences/<app>) to the new path (~/Library/Application Support/<app>) on first launch. Pin your platformdirs version in production if you cannot migrate users automatically.","message":"macOS user_config_dir path has changed twice across major versions: 2.0.0 moved it to ~/Library/Preferences/<app>, then 3.0.0 moved it back to ~/Library/Application Support/<app>. Any stored config files at the old path will silently go unread after upgrading across these boundaries.","severity":"breaking","affected_versions":"<3.0.0"},{"fix":"If upgrading from <2.6.0, migrate or symlink ~/.cache/<app>/log to ~/.local/state/<app>/log, or pin to <2.6.0 until migration is complete.","message":"Linux user_log_dir was corrected in 2.6.0 from XDG_CACHE_HOME to XDG_STATE_HOME (i.e. ~/.cache/<app>/log → ~/.local/state/<app>/log). Existing log files at the old location are silently abandoned.","severity":"breaking","affected_versions":"<2.6.0"},{"fix":"To test platform-specific paths in tests, reload the platformdirs module after patching sys.platform, or use unittest.mock.patch combined with importlib.reload(platformdirs).","message":"Platform detection happens at import time, not at call time. Monkeypatching sys.platform after import has no effect on which platform class is used. This differs from the old appdirs behavior.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Use platformdirs <4 for Python 3.8 or 3.9 support, or upgrade your Python runtime.","message":"Requires Python >=3.10 as of the current release series. Older Python versions are not supported.","severity":"breaking","affected_versions":">=4.x"},{"fix":"Pass ensure_exists=True to PlatformDirs() or the functional API call, or manually call Path(dirs.user_data_dir).mkdir(parents=True, exist_ok=True) before writing.","message":"Directories are NOT created on disk by default. Accessing dirs.user_data_dir returns a string path but does not mkdir. Code that immediately opens a file in that path will raise FileNotFoundError.","severity":"gotcha","affected_versions":"all"},{"fix":"Split with dirs.site_data_dir.split(os.pathsep) or use the iter_data_dirs() / iter_config_dirs() iterator methods on the PlatformDirs instance to get individual Path objects.","message":"site_data_dir and site_config_dir with multipath=True return a colon-separated string on Unix (os.pathsep-joined), not a list. Iterating the string character-by-character is a common mistake.","severity":"gotcha","affected_versions":"all"},{"fix":"Pass use_site_for_root=True to PlatformDirs() when you want system-wide paths when running as root on Unix.","message":"On Unix, running as root (uid 0) does NOT redirect user_*_dir to site_*_dir by default for backward compatibility. Root's XDG dirs point to /root/.local/share etc., not /usr/local/share.","severity":"gotcha","affected_versions":">=4.8.0"}],"env_vars":null,"last_verified":"2026-05-12T12:37:50.658Z","next_check":"2026-06-26T00:00:00.000Z","problems":[{"fix":"pip install platformdirs","cause":"The 'platformdirs' package is not installed in the Python environment being used, or the environment is not correctly activated.","error":"ModuleNotFoundError: No module named 'platformdirs'"},{"fix":"Add 'platformdirs' as a hidden import to your PyInstaller command or .spec file: `pyinstaller --hidden-import platformdirs your_script.py`","cause":"This error often occurs when bundling an application with PyInstaller; a dependency (like pkg_resources) requires 'platformdirs', but PyInstaller fails to detect and include it automatically.","error":"ImportError: The 'platformdirs' package is required"},{"fix":"Explicitly include the platform-specific submodule as a hidden import in your PyInstaller command or .spec file: `pyinstaller --hidden-import platformdirs.macos your_script.py` (adjust 'macos' for other platforms like 'windows' or 'unix' if applicable).","cause":"When using PyInstaller, platform-specific submodules like 'platformdirs.macos' are dynamically imported, which PyInstaller may fail to detect and include, leading to this error on the respective OS.","error":"ModuleNotFoundError: No module named 'platformdirs.macos'"},{"fix":"Upgrade the 'platformdirs' package to the latest version or a version compatible with your dependent library: `pip install --upgrade platformdirs`","cause":"A dependent library is attempting to access an attribute or function (e.g., 'site_cache_dir') that exists in a newer version of 'platformdirs' but is missing from the currently installed older version.","error":"AttributeError: module 'platformdirs' has no attribute 'site_cache_dir'"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":80,"quickstart_tag":"verified","pypi_latest":null,"install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.04,"mem_mb":2,"disk_size":"18.0M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":2.1,"disk_size":"19M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.07,"mem_mb":2.3,"disk_size":"19.9M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.05,"mem_mb":2.3,"disk_size":"20M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.05,"mem_mb":2,"disk_size":"11.7M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.05,"mem_mb":2,"disk_size":"12M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.04,"mem_mb":2,"disk_size":"11.4M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.04,"mem_mb":1.8,"disk_size":"12M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.03,"mem_mb":1.5,"disk_size":"17.5M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":1.5,"disk_size":"18M"}]},"quickstart_checks":{"last_tested":"2026-04-23","tag":"verified","tag_description":"quickstart runs on critical runtimes, recently tested","results":[{"runtime":"python:3.10-alpine","exit_code":0},{"runtime":"python:3.10-slim","exit_code":0},{"runtime":"python:3.11-alpine","exit_code":0},{"runtime":"python:3.11-slim","exit_code":0},{"runtime":"python:3.12-alpine","exit_code":0},{"runtime":"python:3.12-slim","exit_code":0},{"runtime":"python:3.13-alpine","exit_code":0},{"runtime":"python:3.13-slim","exit_code":0},{"runtime":"python:3.9-alpine","exit_code":0},{"runtime":"python:3.9-slim","exit_code":0}]}}