Why is os.path.expanduser not returning the home directory?

那年仲夏 提交于 2020-12-05 10:12:25

问题


I am making a python desktop application that saves a log as a .csv file in the user's Documents folder on Windows. The application is written in python 2.7 and kivy 1.8.0, packaged as a Windows program using pyinstaller 2.1, and the installer is made using Inno Setup Compiler. In this post, I will replace the user's real name with USER.

I have the following lines of code:

DOCUMENTS = os.path.expanduser('~\\Documents\\')
print DOCUMENTS
with open(DOCUMENTS + 'data_log.csv', 'ab') as f:
    do stuff

On my computer and one other I've tested it on, the program works as expected. DOCUMENTS evaluates to 'C:\Users\USER\Documents\'. However, on the three other computers I've tried, DOCUMENTS evaluates to 'C:\Users\USER\AppData\Roaming\SPB_16.6\Documents\'. The program then crashes when it tries to create data_log.csv, giving the following error:

IOError: [Errno 2] No such file or directory: 'C:\\Users\\USER\\AppData\Roaming\\SPB_16.6\\Documents\\data_log.csv'

First, why might os.path.expanduser misbehave on certain systems, but not on others?

Second, even if it's in the wrong directory, open() should create the file if it doesn't exist, so why is that causing it to crash?

I've figured out what's causing this problem. On most systems, HOME is None, so os.path.expanduser uses USERPROFILE instead. However, in rare cases HOME is set to something like C:\SPB\ or C:\Users\USER\AppData\Roaming\SPB_16.6. My solution is to use os.environ to access USERPROFILE directly instead of using os.path.expanduser.


回答1:


From the documentation of expanduser:

On Windows, HOME and USERPROFILE will be used if set, otherwise a combination of HOMEPATH and HOMEDRIVE will be used. An initial ~user is handled by stripping the last directory component from the created user path derived above.

As you can see, the code is extremely simple (dumped with inspect):

def expanduser(path):
    """Expand ~ and ~user constructs.

    If user or $HOME is unknown, do nothing."""
    if path[:1] != '~':
        return path
    i, n = 1, len(path)
    while i < n and path[i] not in '/\\':
        i = i + 1

    if 'HOME' in os.environ:
        userhome = os.environ['HOME']
    elif 'USERPROFILE' in os.environ:
        userhome = os.environ['USERPROFILE']
    elif not 'HOMEPATH' in os.environ:
        return path
    else:
        try:
            drive = os.environ['HOMEDRIVE']
        except KeyError:
            drive = ''
        userhome = join(drive, os.environ['HOMEPATH'])

    if i != 1: #~user
        userhome = join(dirname(userhome), path[1:i])

    return userhome + path[i:]

There's not much that can go wrong with expanduser itself. You'll want to check those environment variables inside your program to see if they hold the correct values.

    import os
    for var in ('HOME', 'USERPROFILE', 'HOMEPATH', 'HOMEDRIVE'):
        print os.environ.get(var)

A likely reason open may be failing is that the directory where you're trying to open the file doesn't exist, or you don't have permissions to access it.



来源:https://stackoverflow.com/questions/24679918/why-is-os-path-expanduser-not-returning-the-home-directory

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!