如何使用 Python 查找 Windows 通用应用程序数据文件夹?

发布于 2024-07-15 04:40:40 字数 57 浏览 5 评论 0原文

我希望我的应用程序存储一些数据以供所有用户访问。 使用Python,我怎样才能找到数据应该去哪里?

I would like my application to store some data for access by all users. Using Python, how can I find where the data should go?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

风启觞 2024-07-22 04:40:40

如果您不想添加像 winpaths 这样的第三方模块的依赖项,我建议使用 Windows 中已有的环境变量:

具体来说,您可能需要 ALLUSERSPROFILE 获取公共用户配置文件文件夹的位置,这是应用程序数据目录所在的位置。

例如:

C:\> python -c "import os; print os.environ['ALLUSERSPROFILE']"
C:\Documents and Settings\All Users

编辑:查看 winpaths 模块,它使用 ctypes,因此如果您只想使用代码的相关部分而不安装 winpath,您可以使用它(显然为了简洁省略了一些错误检查) 。

import ctypes
from ctypes import wintypes, windll

CSIDL_COMMON_APPDATA = 35

_SHGetFolderPath = windll.shell32.SHGetFolderPathW
_SHGetFolderPath.argtypes = [wintypes.HWND,
                            ctypes.c_int,
                            wintypes.HANDLE,
                            wintypes.DWORD, wintypes.LPCWSTR]


path_buf = wintypes.create_unicode_buffer(wintypes.MAX_PATH)
result = _SHGetFolderPath(0, CSIDL_COMMON_APPDATA, 0, 0, path_buf)
print path_buf.value

运行示例:

C:\> python get_common_appdata.py
C:\Documents and Settings\All Users\Application Data

If you don't want to add a dependency for a third-party module like winpaths, I would recommend using the environment variables already available in Windows:

Specifically you probably want ALLUSERSPROFILE to get the location of the common user profile folder, which is where the Application Data directory resides.

e.g.:

C:\> python -c "import os; print os.environ['ALLUSERSPROFILE']"
C:\Documents and Settings\All Users

EDIT: Looking at the winpaths module, it's using ctypes so if you wanted to just use the relevant part of the code without installing winpath, you can use this (obviously some error checking omitted for brevity).

import ctypes
from ctypes import wintypes, windll

CSIDL_COMMON_APPDATA = 35

_SHGetFolderPath = windll.shell32.SHGetFolderPathW
_SHGetFolderPath.argtypes = [wintypes.HWND,
                            ctypes.c_int,
                            wintypes.HANDLE,
                            wintypes.DWORD, wintypes.LPCWSTR]


path_buf = wintypes.create_unicode_buffer(wintypes.MAX_PATH)
result = _SHGetFolderPath(0, CSIDL_COMMON_APPDATA, 0, 0, path_buf)
print path_buf.value

Example run:

C:\> python get_common_appdata.py
C:\Documents and Settings\All Users\Application Data
世界如花海般美丽 2024-07-22 04:40:40

来自 http://snipplr.com/view.php?codeview&id=7354

homedir = os.path.expanduser('~')

# ...works on at least windows and linux. 
# In windows it points to the user's folder 
#  (the one directly under Documents and Settings, not My Documents)


# In windows, you can choose to care about local versus roaming profiles.
# You can fetch the current user's through PyWin32.
#
# For example, to ask for the roaming 'Application Data' directory:
#  (CSIDL_APPDATA asks for the roaming, CSIDL_LOCAL_APPDATA for the local one)
#  (See microsoft references for further CSIDL constants)
try:
    from win32com.shell import shellcon, shell            
    homedir = shell.SHGetFolderPath(0, shellcon.CSIDL_APPDATA, 0, 0)

except ImportError: # quick semi-nasty fallback for non-windows/win32com case
    homedir = os.path.expanduser("~")

要获取所有用户而不是当前用户的应用程序数据目录,只需使用 shellcon.CSIDL_COMMON_APPDATA 而不是 shellcon.CSIDL_APPDATA

From http://snipplr.com/view.php?codeview&id=7354

homedir = os.path.expanduser('~')

# ...works on at least windows and linux. 
# In windows it points to the user's folder 
#  (the one directly under Documents and Settings, not My Documents)


# In windows, you can choose to care about local versus roaming profiles.
# You can fetch the current user's through PyWin32.
#
# For example, to ask for the roaming 'Application Data' directory:
#  (CSIDL_APPDATA asks for the roaming, CSIDL_LOCAL_APPDATA for the local one)
#  (See microsoft references for further CSIDL constants)
try:
    from win32com.shell import shellcon, shell            
    homedir = shell.SHGetFolderPath(0, shellcon.CSIDL_APPDATA, 0, 0)

except ImportError: # quick semi-nasty fallback for non-windows/win32com case
    homedir = os.path.expanduser("~")

To get the app-data directory for all users, rather than the current user, just use shellcon.CSIDL_COMMON_APPDATA instead of shellcon.CSIDL_APPDATA.

任谁 2024-07-22 04:40:40

请查看http://ginstrom.com/code/winpaths.html。 这是一个简单的模块,用于检索 Windows 文件夹信息。 该模块实现 get_common_appdata 来获取所有用户的 App Data 文件夹。

Take a look at http://ginstrom.com/code/winpaths.html. This is a simple module that will retrieve Windows folder information. The module implements get_common_appdata to get the App Data folder for all users.

我的黑色迷你裙 2024-07-22 04:40:40

您可以使用 os 模块中的 os.environ 字典访问所有操作系统环境变量。 不过,从字典中选择使用哪个键可能很棘手。 特别是,在使用这些路径时,您应该注意 Windows 的国际化(即非英语)版本。

os.environ['ALLUSERSPROFILE'] 应该为您提供计算机上所有用户的根目录,但之后请注意不要对“应用程序数据”之类的子目录名称进行硬编码,因为这些目录不会不存在于非英语版本的 Windows 上。 就此而言,您可能需要研究一下哪些版本的 Windows 可以设置 ALLUSERSPROFILE 环境变量(我自己也不知道——它可能是通用的)。

我这里的XP机器有一个COMMONAPPDATA环境变量,它指向All Users\Application Data文件夹,但是我的Win2K3系统没有这个环境变量。

You can access all of your OS environment variables using the os.environ dictionary in the os module. Choosing which key to use from that dictionary could be tricky, though. In particular, you should remain aware of internationalized (i.e., non-English) versions of Windows when using these paths.

os.environ['ALLUSERSPROFILE'] should give you the root directory for all users on the computer, but after that be careful not to hard code subdirectory names like "Application Data," because these directories don't exist on non-English versions of Windows. For that matter, you may want to do some research on what versions of Windows you can expect to have the ALLUSERSPROFILE environment variable set (I don't know myself -- it may be universal).

My XP machine here has a COMMONAPPDATA environment variable which points to the All Users\Application Data folder, but my Win2K3 system does not have this environment variable.

零度℉ 2024-07-22 04:40:40

由于与非美国版本的 Windows 和 Vista 不兼容,之前的答案被删除。

编辑: 要扩展 Out Into Space 的答案,您可以使用
winpaths.get_common_appdata 函数。 您可以使用 easy_install winpaths 或访问 pypi 页面 http 来获取 winpaths ://pypi.python.org/pypi/winpaths/,并下载 .exe 安装程序。

Previous answer removed due to incompatibility with non-US versions of Windows, and Vista.

EDIT: To expand on Out Into Space's answer, you would use the
winpaths.get_common_appdata function. You can get winpaths using easy_install winpaths or by going to the pypi page, http://pypi.python.org/pypi/winpaths/, and downloading the .exe installer.

南薇 2024-07-22 04:40:40

由于 SHGetFolderPath 已弃用,您还可以使用 SHGetKnownFolderPath。 这还可以让您查找比 SHGetFolderPath 更多的路径。 这是一个精简示例(完整代码可在 Gist 上找到):

import ctypes, sys
from ctypes import windll, wintypes
from uuid import UUID

class GUID(ctypes.Structure):   # [1]
    _fields_ = [
        ("Data1", wintypes.DWORD),
        ("Data2", wintypes.WORD),
        ("Data3", wintypes.WORD),
        ("Data4", wintypes.BYTE * 8)
    ] 

    def __init__(self, uuid_):
        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

class FOLDERID:     # [2]
    LocalAppData            = UUID('{F1B32785-6FBA-4FCF-9D55-7B8E7F157091}')
    LocalAppDataLow         = UUID('{A520A1A4-1780-4FF6-BD18-167343C5AF16}')
    RoamingAppData          = UUID('{3EB685DB-65F9-4CF6-A03A-E3EF65729F3D}')

class UserHandle:   # [3]
    current = wintypes.HANDLE(0)
    common  = wintypes.HANDLE(-1)

_CoTaskMemFree = windll.ole32.CoTaskMemFree     # [4]
_CoTaskMemFree.restype= None
_CoTaskMemFree.argtypes = [ctypes.c_void_p]

_SHGetKnownFolderPath = windll.shell32.SHGetKnownFolderPath     # [5] [3]
_SHGetKnownFolderPath.argtypes = [
    ctypes.POINTER(GUID), wintypes.DWORD, wintypes.HANDLE, ctypes.POINTER(ctypes.c_wchar_p)
] 

class PathNotFoundException(Exception): pass

def get_path(folderid, user_handle=UserHandle.common):
    fid = GUID(folderid) 
    pPath = ctypes.c_wchar_p()
    S_OK = 0
    if _SHGetKnownFolderPath(ctypes.byref(fid), 0, user_handle, ctypes.byref(pPath)) != S_OK:
        raise PathNotFoundException()
    path = pPath.value
    _CoTaskMemFree(pPath)
    return path

common_data_folder = get_path(FOLDERID.RoamingAppData)

# [1] http://msdn.microsoft.com/en-us/library/windows/desktop/aa373931.aspx
# [2] http://msdn.microsoft.com/en-us/library/windows/desktop/dd378457.aspx
# [3] http://msdn.microsoft.com/en-us/library/windows/desktop/bb762188.aspx
# [4] http://msdn.microsoft.com/en-us/library/windows/desktop/ms680722.aspx
# [5] http://www.themacaque.com/?p=954

Since SHGetFolderPath is deprecated, you can also use SHGetKnownFolderPath in Vista and newer. This also lets you look up more paths than SHGetFolderPath will. Here's a stripped-down example (full code available on Gist):

import ctypes, sys
from ctypes import windll, wintypes
from uuid import UUID

class GUID(ctypes.Structure):   # [1]
    _fields_ = [
        ("Data1", wintypes.DWORD),
        ("Data2", wintypes.WORD),
        ("Data3", wintypes.WORD),
        ("Data4", wintypes.BYTE * 8)
    ] 

    def __init__(self, uuid_):
        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

class FOLDERID:     # [2]
    LocalAppData            = UUID('{F1B32785-6FBA-4FCF-9D55-7B8E7F157091}')
    LocalAppDataLow         = UUID('{A520A1A4-1780-4FF6-BD18-167343C5AF16}')
    RoamingAppData          = UUID('{3EB685DB-65F9-4CF6-A03A-E3EF65729F3D}')

class UserHandle:   # [3]
    current = wintypes.HANDLE(0)
    common  = wintypes.HANDLE(-1)

_CoTaskMemFree = windll.ole32.CoTaskMemFree     # [4]
_CoTaskMemFree.restype= None
_CoTaskMemFree.argtypes = [ctypes.c_void_p]

_SHGetKnownFolderPath = windll.shell32.SHGetKnownFolderPath     # [5] [3]
_SHGetKnownFolderPath.argtypes = [
    ctypes.POINTER(GUID), wintypes.DWORD, wintypes.HANDLE, ctypes.POINTER(ctypes.c_wchar_p)
] 

class PathNotFoundException(Exception): pass

def get_path(folderid, user_handle=UserHandle.common):
    fid = GUID(folderid) 
    pPath = ctypes.c_wchar_p()
    S_OK = 0
    if _SHGetKnownFolderPath(ctypes.byref(fid), 0, user_handle, ctypes.byref(pPath)) != S_OK:
        raise PathNotFoundException()
    path = pPath.value
    _CoTaskMemFree(pPath)
    return path

common_data_folder = get_path(FOLDERID.RoamingAppData)

# [1] http://msdn.microsoft.com/en-us/library/windows/desktop/aa373931.aspx
# [2] http://msdn.microsoft.com/en-us/library/windows/desktop/dd378457.aspx
# [3] http://msdn.microsoft.com/en-us/library/windows/desktop/bb762188.aspx
# [4] http://msdn.microsoft.com/en-us/library/windows/desktop/ms680722.aspx
# [5] http://www.themacaque.com/?p=954
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文