2009-03-09 24 views
29

私のアプリケーションでは、すべてのユーザーがアクセスできるようにいくつかのデータを保存したいと思います。 Pythonを使って、データをどこに置かなければならないのでしょうか?Pythonを使用してWindowsの共通アプリケーションデータフォルダを見つけるにはどうすればよいですか?

+0

これはどのオペレーティングシステムですか? – tgray

+2

@tgray、それは質問タイトルです。 –

+15

これはちょっと恥ずかしいです... – tgray

答えて

38

あなたはwinpathsのようなサードパーティモジュールの依存関係を追加したくない場合は、私はWindowsですでに利用可能な環境変数を使用することをお勧めします:

具体的に、あなたはおそらくALLUSERSPROFILEに、Application Dataディレクトリが存在する共通のユーザープロファイルフォルダの場所を取得する必要があります。

例:

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

EDIT:あなただけwinpathをインストールしなくても、コードの関連部分を使用したい場合、あなたは明らかにいくつか(これを使用することができますので、winpathsモジュールを見てみると、それはctypesのを使用しています簡潔さのためにエラーチェックが省略されています)。

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 

例の実行:あなたはosモジュールでos.environ辞書を使用して、OSの環境変数のすべてにアクセスすることができます

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

ユーザーが英語以外のバージョンのWindowsを使用している場合はどうなりますか? ALLUSERSPROFILEは引き続き適用されますか? –

+0

@Out Into Space - 少なくともイタリア語版のウィンドウでは、他の英語以外のバージョンについてはわかりません。 – Jay

+0

クール、知っておいてよかった! –

10

http://ginstrom.com/code/winpaths.htmlをご覧ください。これは、Windowsフォルダ情報を取得する簡単なモジュールです。このモジュールは、すべてのユーザーのApp Dataフォルダを取得するためにget_common_appdataを実装しています。

+0

+1これはとても役に立ちますが、感謝ですが、ジェイズの答えは、私が依存関係を持たずに欲しいものです。 –

3

以前の回答は、米国以外のバージョンのWindowsとVistaとの互換性がないため削除されました。

EDIT:宇宙の答えに出で展開するには、あなたが winpaths.get_common_appdata機能を使用します。 easy_install winpathsを使用するか、pypiページhttp://pypi.python.org/pypi/winpaths/にアクセスし、.exeインストーラをダウンロードすることで、勝者パスを得ることができます。

+0

残念ながら、それは英語以外のOSでは成立しません。 – Jeff

+0

より具体的に教えてください。 – tgray

+0

私は彼が "Documents and Settings"はXPの英語以外のコピーにローカライズされているということを彼は信じています。また、レジストリを介してこのフォルダの場所を変更することも可能です。最後に、Vistaではこのフォルダに「Users」という名前が付けられています。レッスン:ハードコードしないでください。 –

3

。ただし、その辞書から使用するキーを選択することは難しいかもしれません。特に、これらのパスを使用する場合は、国際化された(つまり、英語以外の)バージョンのWindowsに注意してください。

os.environ['ALLUSERSPROFILE']は、コンピュータ上のすべてのユーザーのルートディレクトリを指定する必要がありますが、英語以外のバージョンのWindowsでは存在しないため、 "Application Data"などのサブディレクトリ名をハードコードしないように注意してください。そのため、ALLUSERSPROFILE環境変数を設定することが期待できるWindowsのバージョンについていくつかの調査をしたいと思うかもしれません(私自身はわかりませんが、普遍的かもしれません)。

私のXPマシンは、ここではすべてのユーザー\ Application Dataフォルダを指すCOMMONAPPDATA環境変数を持っていますが、私のWin2K3システムにはこの環境変数がありません。

12

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を使用し、むしろ現在のユーザーよりも、すべてのユーザーのためのアプリ - データディレクトリを取得します。

+0

OPがすべてのユーザーからアクセス可能なデータを要求しました –

+1

@ Jason S:すべてのユーザーにapp-dataを書き留めました。 –

+0

編集に感謝します! –

0

SHGetFolderPathは廃止予定ですので、Vista以降ではSHGetKnownFolderPathを使用することもできます。これにより、SHGetFolderPathより多くのパスを参照することもできます。除外された例(フルコード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 
関連する問題