2009-03-09 17 views

Respuesta

38

Si no desea agregar una dependencia de un módulo de terceros, como winpaths, recomendaría el uso de las variables de entorno que ya están disponibles en Windows:

Específicamente se probablemente desee ALLUSERSPROFILE para obtener la ubicación de la carpeta de perfil de usuario común, que es donde reside el directorio de datos de la aplicación.

por ejemplo:

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

EDITAR: Mirando el módulo de winpaths, se trata de utilizar ctypes por lo que si desea utilizar sólo la parte correspondiente del código sin necesidad de instalar WinPath, puede utilizar esta (obviamente algunos error de verificación omitida por brevedad).

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 

Ejemplo de ejecución:

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

¿Qué sucede si el usuario tiene una versión de Windows que no está en inglés? ¿ALLUSERSPROFILE todavía se aplica? –

+0

@Out Into Space: lo hace al menos en la versión italiana de Windows, no está seguro de otras versiones que no sean en inglés. – Jay

+0

Genial, es bueno saberlo! –

10

Eche un vistazo a http://ginstrom.com/code/winpaths.html. Este es un módulo simple que recuperará la información de la carpeta de Windows. El módulo implementa get_common_appdata para obtener la carpeta de datos de la aplicación para todos los usuarios.

+0

+1 Esto se ve muy útil, gracias, pero la respuesta de Jays me da lo que quiero sin ninguna dependencia añadida –

3

Se eliminó la respuesta anterior debido a la incompatibilidad con las versiones de Windows y Windows que no son de EE. UU.

EDIT: Para ampliar Salir al respuesta de espacio, se utiliza la función winpaths.get_common_appdata. Puede obtener winpaths usando easy_install winpaths o yendo a la página de pypi, http://pypi.python.org/pypi/winpaths/, y descargando el instalador .exe.

+0

Desafortunadamente, eso no se mantendrá en sistemas operativos que no están en inglés. – Jeff

+0

¿Podría ser más específico, por favor? – tgray

+0

Creo que quiere decir que "Documentos y configuraciones" está localizado en copias de XP que no están en inglés. Además, es posible cambiar la ubicación de esta carpeta a través del registro. Finalmente, Vista nombra esta carpeta "Usuarios" en su lugar. Lección: no codificarlo. –

3

Puede acceder a todas las variables de entorno del sistema operativo utilizando el diccionario os.environ en el módulo os. Sin embargo, elegir qué tecla usar de ese diccionario podría ser complicado. En particular, debe conocer las versiones internacionalizadas (es decir, no inglesas) de Windows al usar estas rutas.

os.environ['ALLUSERSPROFILE'] debería darle el directorio raíz para todos los usuarios en la computadora, pero después tenga cuidado de no codificar los nombres de los subdirectorios como "Datos de la aplicación" porque estos directorios no existen en versiones de Windows que no sean en inglés. Para ese caso, es posible que desee investigar qué versiones de Windows puede esperar tener la variable de entorno ALLUSERSPROFILE establecida (no sé yo mismo, puede ser universal).

Mi máquina XP aquí tiene una variable de entorno COMMONAPPDATA que apunta a la carpeta All Users \ Application Data, pero mi sistema Win2K3 no tiene esta variable de entorno.

12

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

Para obtener el directorio app-datos para todos los usuarios, en lugar de que el usuario actual, sólo tiene que utilizar en lugar de shellcon.CSIDL_COMMON_APPDATAshellcon.CSIDL_APPDATA.

+0

OP solicitó datos accesibles por todos los usuarios –

+1

@Jason S: He agregado una nota sobre la aplicación de datos para todos los usuarios. –

+0

gracias por la edición! –

0

Dado que SHGetFolderPath está obsoleto, también puede usar SHGetKnownFolderPath en Vista y versiones más recientes. Esto también le permite buscar más rutas que SHGetFolderPath. Aquí hay un ejemplo desglosado (código completo 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 
Cuestiones relacionadas