Как найти общую папку данных приложения Windows с помощью Python?

Я хотел бы, чтобы мое приложение сохраняло некоторые данные для доступа всех пользователей. Используя Python, как я могу найти, куда должны идти данные?

Если вы не хотите добавлять зависимость для стороннего модуля, такого как winpath, я бы рекомендовал использовать переменные среды, которые уже доступны в Windows:

  • Какие переменные среды доступны в Windows?

В частности, вы, вероятно, хотите, чтобы ALLUSERSPROFILE установил местоположение общей папки профиля пользователя, в которой находится каталог данных приложения.

например:

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

EDIT : смотря на модуль 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 

С 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 .

Взгляните на http://ginstrom.com/code/winpaths.html . Это простой модуль, который будет получать информацию о папке Windows. Модуль реализует get_common_appdata для получения папки данных приложения для всех пользователей.

Вы можете получить доступ ко всем переменным среды вашей ОС, используя словарь os.environ в модуле os . Выбор какой клавиши для использования из этого словаря может быть сложным. В частности, вы должны оставаться в курсе интернационализированных (т.е. неанглийских) версий Windows при использовании этих путей.

os.environ['ALLUSERSPROFILE'] должен предоставить вам корневой каталог для всех пользователей на компьютере, но после этого будьте осторожны, чтобы не писать имена подкаталогов жесткого кода, такие как «Данные приложения», потому что эти каталоги не существуют на неанглийских версиях Windows. В этом случае вам может понадобиться провести некоторое исследование того, какие версии Windows вы можете ожидать, чтобы установить переменную среды ALLUSERSPROFILE (я не знаю сам – она ​​может быть универсальной).

У моей машины XP здесь есть переменная среды COMMONAPPDATA, которая указывает на папку «Все пользователи \ Приложения», но моя система Win2K3 не имеет этой переменной среды.

Предыдущий ответ удален из-за несовместимости с неамериканскими версиями Windows и Vista.

EDIT: Чтобы расширить ответ Out Into Space, вы должны использовать функцию winpaths.get_common_appdata . Вы можете получить winpath с помощью easy_install winpaths или перейдя на страницу pypi, http://pypi.python.org/pypi/winpaths/ и загрузив программу .exe.

Поскольку SHGetFolderPath устарел, вы также можете использовать SHGetKnownFolderPath в Vista и новее. Это также позволяет вам искать больше путей, чем 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 
Interesting Posts