Python:以跨平台的方式获取AppData文件夹

30

我需要一个代码片段,可以在所有平台(至少包括Win/Mac/Linux)中获取应用程序数据(配置文件等)的正确目录。例如:在Windows上为% APPDATA%/。

7个回答

20

如果你不介意使用appdirs模块,它应该可以解决你的问题。(代价=你需要安装该模块或直接在Python应用程序中包含它。)


@Taylor D Edmiston 请添加您自己的答案。 - Jason S
2
为什么要撤销添加自 readme 的用法示例以使此答案完整的编辑?正如您所知,好的答案应该是完整的,而不仅仅是“点击此链接”。删除高度相关和有价值的使用信息感觉有点被动攻击...根据 https://stackoverflow.com/help/how-to-answer:鼓励链接到外部资源,但请在链接周围添加上下文,以便您的同行用户了解它的用途和存在的原因。**始终引用重要链接的最相关部分,以防外部资源无法访问或永久离线。** - Taylor D. Edmiston
请添加您自己的答案。如果您编辑我的答案使其更好,但显著不同,则它不再是我的答案。欢迎您提出建议,但请不要代替我进行编辑。 - Jason S
这确实会使它与作者的意图显著不同,并产生冲突。这不是维基百科。我想说的是,如果你想改进,就发表你自己的答案;我甚至会点赞。 - Jason S
3
我理解您的观点,但是值得一提的是,在编辑帖子指南中,SO明确提到“所有贡献都在创意共用许可下授权,而且本站像维基百科一样进行协作编辑。”- https://stackoverflow.com/help/editing。 - Taylor D. Edmiston

15

Qt的QStandardPaths文档列出了以下路径。

使用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

Python文档建议使用sys.platform.startswith('linux')这个“习惯用法”以便与旧版本的Python兼容,因为旧版本会返回类似于“linux2”或“linux3”的内容。


1
我建议遵循Linux的$XDG_DATA_HOME规范和Windows的%APPDATA%或%LOCALAPPDATA%,而不是硬编码。Qt路径实际上是备用方案,以防这些变量未设置。一旦我的PR合并,明天我会添加一个示例代码链接。 - aadibajpai
1
无法编辑,但是这是链接:https://github.com/SwagLyrics/SwagLyrics-For-Spotify/blob/master/swaglyrics/__init__.py#L8-L32 - aadibajpai

3

您可以使用以下函数获取用户数据目录,已在Linux和Windows 10上进行测试(返回AppData/Local目录),该函数改编自appdirs包:

import sys
from pathlib import Path
from os import getenv

def get_user_data_dir(appname):
    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)


1

appdata包和appdirs有什么不同? - Taylor D. Edmiston
4
@TaylorD.Edmiston 嗯,就我看来实际上没有什么区别。在我开发 appdata 的时候,我对 appdirs 一无所知。 - voilalex

1
我建议研究您想在其中使用此程序的操作系统中“appdata”文件夹的位置。一旦您知道了这些位置,就可以使用if语句来检测操作系统并执行某些操作。
import sys
if sys.platform == "platform_value":
    do_something()
elif sys.platform == "platform_value":
    do_something()
  • 系统: platform_value
  • Linux (2.x 和 3.x): 'linux2'
  • Windows: 'win32'
  • Windows/Cygwin: 'cygwin'
  • Mac OS X: 'darwin'
  • OS/2: 'os2'
  • OS/2 EMX: 'os2emx'
  • RiscOS: 'riscos'
  • AtheOS: 'atheos'

列表来自Python官方文档。(搜索 'sys.platform')


1
我相信那只在Windows上有效。我想要跨平台 :) - user1438098
4
Python的核心思想是将事物抽象为通用库;为什么没有一个通用函数来完成这个任务? - Jason S

0
如果你正在寻找config目录,这里有一个解决方案,默认为~/.config,除非在方法的localplatforms:字典中有特定于平台(sys.platform)的条目。
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')

这适用于Windows、Mac和Linux,但是可以更容易地扩展,根据需要。


0

我遇到了一个类似的问题,我想要动态地解析所有的Windows %路径,而不需要事先知道它们。你可以使用 os.path.expandvars 来动态解析这些路径。就像这样:

from os import path

appdatapath = '%APPDATA%\MyApp'
if '%' in appdatapath:
    appdatapath = path.expandvars(appdatapath)
print(appdatapath)

最后一行将打印:C:\Users\\{user}\AppData\Roaming\MyApp 这适用于Windows,但我尚未在Linux上测试过。只要路径由环境定义,那么expandvars应该能够找到它。您可以在此处阅读有关expand vars的更多信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接