【问题标题】:Why is os.path.expanduser not returning the home directory?为什么 os.path.expanduser 不返回主目录?
【发布时间】:2014-09-01 00:39:50
【问题描述】:

我正在制作一个 python 桌面应用程序,它将日志作为 .csv 文件保存在 Windows 上用户的 Documents 文件夹中。该应用程序是用 python 2.7 和 kivy 1.8.0 编写的,使用 pyinstaller 2.1 打包为 Windows 程序,安装程序是使用 Inno Setup Compiler 制作的。在这篇文章中,我会将用户的真实姓名替换为 USER。

我有以下几行代码:

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

在我的计算机和我测试过的另一台计算机上,程序按预期运行。 DOCUMENTS 评估为“C:\Users\USER\Documents\”。但是,在我尝试过的其他三台计算机上,DOCUMENTS 的计算结果为“C:\Users\USER\AppData\Roaming\SPB_16.6\Documents\”。然后程序在尝试创建 data_log.csv 时崩溃,并出现以下错误:

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

首先,为什么 os.path.expanduser 可能在某些系统上行为不端,而在其他系统上却没有?

其次,即使在错误的目录下,如果文件不存在,open() 也应该创建文件,那为什么会导致它崩溃呢?

我已经弄清楚是什么导致了这个问题。在大多数系统上,HOME 是 None,所以 os.path.expanduser 使用 USERPROFILE 代替。但是,在极少数情况下,HOME 设置为 C:\SPB\ 或 C:\Users\USER\AppData\Roaming\SPB_16.6 之类的内容。我的解决方案是使用os.environ直接访问USERPROFILE,而不是使用os.path.expanduser。

【问题讨论】:

  • 它崩溃的机器和它运行的机器之间有什么主要区别吗?
  • 我想不到。它适用的 2 都有 Windows 7,但它在其他 Windows 7 机器和一台可用的 Windows 8 机器上崩溃。没有用户可以更改任何机器上的任何隐藏系统设置、环境变量等。

标签: python windows path os.path


【解决方案1】:

来自expanduser的文档:

在 Windows 上,如果设置了 HOME 和 USERPROFILE,将使用,否则 将使用 HOMEPATH 和 HOMEDRIVE 的组合。一个初始的~用户 通过从创建的最后一个目录组件中剥离来处理 上面派生的用户路径。

如您所见,代码极其简单(转储为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:]

expanduser 本身不会出错。您需要检查程序中的这些环境变量,看看它们是否包含正确的值。

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

open 失败的一个可能原因是您尝试打开文件的目录不存在,或者您没有访问该文件的权限。

【讨论】:

  • 他们持有正确的值,但我仍然得到这个错误。
  • @user268639 我们能得到更多细节吗? “坏”系统中这些变量的具体值是什么?
  • @user268639 另外,重要的是,您是如何执行脚本的?直接从控制台?还是其他应用启动的?
  • 如果 OP 没有写入权限,则会出现权限被拒绝错误
  • 很难收集详细信息,因为我只是要求朋友和同事运行程序,而不是自己完全访问计算机。无论如何,在我的“好”系统上,HOME 是 None,USERPROFILE 是 C:\Users\MyName,HOMEPATH 是 \Users\MyName,HOMEDRIVE 是 C:。在其中一个“坏”系统上,它们完全相同(当然,更改了 MyName)。
猜你喜欢
  • 2017-10-07
  • 2011-11-27
  • 1970-01-01
  • 2013-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-05
相关资源
最近更新 更多