2009-03-09 25 views

Trả lời

38

Nếu bạn không muốn thêm một sự phụ thuộc đối với một mô-đun của bên thứ ba như winpaths, tôi sẽ khuyên bạn sử dụng các biến môi trường đã có sẵn trong Windows:

Cụ thể bạn có lẽ muốn ALLUSERSPROFILE để có được vị trí của thư mục hồ sơ người dùng chung, là nơi chứa thư mục Dữ liệu ứng dụng.

ví dụ:

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

EDIT: Nhìn vào mô-đun winpaths, nó sử dụng ctypes vì ​​vậy nếu bạn muốn chỉ cần sử dụng một phần có liên quan của mã mà không cần cài winpath, bạn có thể sử dụng này (rõ ràng là một số kiểm tra lỗi bị bỏ qua cho ngắn gọn).

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 

Ví dụ chạy:

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

Điều gì sẽ xảy ra nếu người dùng sử dụng phiên bản Windows không phải tiếng Anh? ALLUSERSPROFILE vẫn áp dụng? –

+0

@Out Into Space - ít nhất là trên phiên bản tiếng Ý của cửa sổ, không chắc chắn về các phiên bản không phải tiếng Anh khác. – Jay

+0

Tuyệt, rất hay để biết! –

10

Hãy xem http://ginstrom.com/code/winpaths.html. Đây là một mô-đun đơn giản sẽ lấy thông tin thư mục Windows. Mô-đun triển khai get_common_appdata để tải thư mục Dữ liệu ứng dụng cho tất cả người dùng.

+0

+1 Điều này có vẻ rất hữu ích, cảm ơn, nhưng Jays câu trả lời cho tôi những gì tôi muốn với không phụ thuộc thêm –

3

Câu trả lời trước bị xóa do không tương thích với các phiên bản Windows không phải của Hoa Kỳ và Vista.

EDIT: Mở rộng trên Out Into câu trả lời Space, bạn sẽ sử dụng chức năng winpaths.get_common_appdata. Bạn có thể nhận được winpaths bằng cách sử dụng easy_install winpaths hoặc bằng cách đi tới trang pypi, http://pypi.python.org/pypi/winpaths/ và tải xuống trình cài đặt .exe.

+0

Thật không may, điều đó sẽ không giữ trên hệ điều hành không phải tiếng Anh. – Jeff

+0

Bạn có thể cụ thể hơn không? – tgray

+0

Tôi tin rằng anh ấy có nghĩa là "Tài liệu và cài đặt" được bản địa hóa trong các bản sao không phải tiếng Anh của XP. Ngoài ra, có thể thay đổi vị trí của thư mục này thông qua sổ đăng ký. Cuối cùng, Vista đặt tên cho thư mục này là "Users". Bài học: không mã hóa nó. –

3

Bạn có thể truy cập vào tất cả các biến môi trường hệ điều hành của bạn bằng cách sử dụng từ điển os.environ trong module os. Tuy nhiên, việc chọn khóa nào để sử dụng từ từ điển đó có thể khó khăn. Cụ thể, bạn nên duy trì nhận thức về các phiên bản Windows được quốc tế hóa (tức là không phải tiếng Anh) khi sử dụng các đường dẫn này.

os.environ['ALLUSERSPROFILE'] sẽ cung cấp cho bạn thư mục gốc cho tất cả người dùng trên máy tính, nhưng sau đó hãy cẩn thận đừng để các tên thư mục con mã cứng như "Dữ liệu ứng dụng" vì các thư mục này không tồn tại trên các phiên bản Windows không phải tiếng Anh. Cho rằng vấn đề, bạn có thể muốn làm một số nghiên cứu về những phiên bản của Windows bạn có thể mong đợi để có bộ biến môi trường ALLUSERSPROFILE (Tôi không biết bản thân mình - nó có thể là phổ quát).

Máy XP của tôi ở đây có biến môi trường COMMONAPPDATA trỏ đến thư mục All Users \ Application Data, nhưng hệ thống Win2K3 của tôi không có biến môi trường này.

12

Từ 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("~") 

Để có được thư mục ứng dụng dữ liệu cho tất cả người dùng, chứ không phải là người sử dụng hiện nay, chỉ cần sử dụng shellcon.CSIDL_COMMON_APPDATA thay vì shellcon.CSIDL_APPDATA.

+0

OP yêu cầu tất cả người dùng truy cập dữ liệu –

+1

@Jason S: Tôi đã thêm ghi chú lại dữ liệu ứng dụng cho tất cả người dùng. –

+0

cảm ơn bạn đã chỉnh sửa! –

0

SHGetFolderPath không được dùng nữa, bạn cũng có thể sử dụng SHGetKnownFolderPath trong Vista và phiên bản mới hơn. Điều này cũng cho phép bạn tra cứu nhiều đường dẫn hơn SHGetFolderPath. Dưới đây là một ví dụ bị tước xuống (mã đầy đủ 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 
Các vấn đề liên quan