How do I find the Windows common application data folder using Python?

后端 未结 6 868
谎友^
谎友^ 2020-11-30 05:55

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?

6条回答
  •  佛祖请我去吃肉
    2020-11-30 06:11

    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
    

提交回复
热议问题