Python NameError:全局名称'__file__'未定义。

162

当我在Python 2.7中运行这段代码时,我遇到了这个错误:

Traceback (most recent call last):
File "C:\Python26\Lib\site-packages\pyutilib.subprocess-3.5.4\setup.py", line 30, in <module>
    long_description = read('README.txt'),
  File "C:\Python26\Lib\site-packages\pyutilib.subprocess-3.5.4\setup.py", line 19, in read
    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
NameError: global name '__file__' is not defined

代码是:

import os
from setuptools import setup


def read(*rnames):
    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()


setup(name="pyutilib.subprocess",
    version='3.5.4',
    maintainer='William E. Hart',
    maintainer_email='wehart@sandia.gov',
    url = 'https://software.sandia.gov/svn/public/pyutilib/pyutilib.subprocess',
    license = 'BSD',
    platforms = ["any"],
    description = 'PyUtilib utilites for managing subprocesses.',
    long_description = read('README.txt'),
    classifiers = [
        'Development Status :: 4 - Beta',
        'Intended Audience :: End Users/Desktop',
        'License :: OSI Approved :: BSD License',
        'Natural Language :: English',
        'Operating System :: Microsoft :: Windows',
        'Operating System :: Unix',
        'Programming Language :: Python',
        'Programming Language :: Unix Shell',
        'Topic :: Scientific/Engineering :: Mathematics',
        'Topic :: Software Development :: Libraries :: Python Modules'],
      packages=['pyutilib', 'pyutilib.subprocess', 'pyutilib.subprocess.tests'],
      keywords=['utility'],
      namespace_packages=['pyutilib'],
      install_requires=['pyutilib.common', 'pyutilib.services']
      )
15个回答

185

当你在Python交互式shell中添加这行代码 os.path.join(os.path.dirname(__file__))时,会出现这个错误。

Python Shell无法检测到当前文件路径中的__file__,这与你添加此行代码的filepath有关。

所以你应该在file.py中写下这行代码os.path.join(os.path.dirname(__file__)),然后运行python file.py。它会工作,因为它采用了你的文件路径。


18
完全同样的经验。但如何在Shell中使其正常工作? - s2t2
2
但是要从脚本运行 file.py,您需要将它放在与脚本相同的目录中。因此,在运行 file.py 之前,您需要切换到该目录... 因此,仍然需要寻找更好的解决方案。 - ztyh
那么当您按下C-c C-p时,Emacs使用交互式shell(python-shell)?有没有一种方法可以将此shell用作运行文件的终端? 运行shell有三个选项:CMD、DEDICATED和SHOW。它们中的一个能完成这个任务吗? - sinekonata
这并不是关于setuptools的答案,因为如果你分发你的包并按照pypi.org的指示使用twine进行构建,那么这个答案中的任何内容都没有帮助,因为setup.py将会在虚拟环境中被复制并执行,从而无法相对地找到孤立的文件。 - Stof

40

我也遇到了使用PyInstaller和Py2exe时的同样问题,后来在cx-freeze的常见问题解答中找到了解决方法。

当您从控制台或应用程序中使用脚本时,下面的函数将提供给您“执行路径”,而不是“实际文件路径”:

print(os.getcwd())
print(sys.argv[0])
print(os.path.dirname(os.path.realpath('__file__')))

来源:
http://cx-freeze.readthedocs.org/en/latest/faq.html

您的旧行(最初的问题):

def read(*rnames):
return open(os.path.join(os.path.dirname(__file__), *rnames)).read()

请使用以下片段替换您的代码行。

def find_data_file(filename):
    if getattr(sys, 'frozen', False):
        # The application is frozen
        datadir = os.path.dirname(sys.executable)
    else:
        # The application is not frozen
        # Change this bit to match where you store your data files:
        datadir = os.path.dirname(__file__)

    return os.path.join(datadir, filename)

使用上述代码,您可以将应用程序添加到操作系统路径中,无论在哪里执行该应用程序,都不会出现无法找到数据/配置文件的问题。

已在以下Python版本进行测试:

  • 3.3.4
  • 2.7.13

2
os.path.realpath('__file__') 不起作用,因为它在引号之间。答案的其余部分是正确的。 - Jean-François Fabre
对我来说,只有在_file_被引号包含时,os.path.realpath('__file__')os.path.abspath('__file__')才能正常工作。@Jean-FrançoisFabre - TeYaP
1
发生的情况是 realpath 不检查 "__file__" 是否存在,它只会返回当前目录 + "/file" 而不做任何检查,因此当 __file__ 未定义时,这与 os.getcwd() 一样好用。真正的解决方案是在主 Python 文件上使用 sys.executable,如答案的其余部分所解释的那样。 - Jean-François Fabre

27

我曾碰到过__file__无法按预期工作的情况。但是以下方法至今未曾让我失望:

import inspect
src_file_path = inspect.getfile(lambda: None)

这是最接近C语言中__FILE__的Python类比。

Python中__file__的行为与C中的__FILE__大不相同。 C版本将提供源文件的原始路径,这在记录错误和知道哪个源文件出现了错误时非常有用。

Python的__file__仅提供当前执行文件的名称,对于日志输出可能没有太多用处。


2
当Python嵌入到另一个应用程序中时,这也可以正常工作。 - sdaau
我用这种方法比os.path.dirname(os.path.realpath(...))方法更成功。 - Mr. S
1
这应该是最佳答案。 - 183.amir
无法在Python 2.7中使用Cython工作。 File "/usr/lib/python2.7/inspect.py", line 419, in getfile 'function, traceback, frame, or code object'.format(object)) TypeError: at 0xb6663e30> 不是一个模块、类、方法、函数、回溯、帧或代码对象 - BrendanSimon

23

请将您的代码更改如下!对我有效。`

os.path.dirname(os.path.abspath("__file__"))

15
我认为你实际上是在使用 os.getcwd(),根据文档,而 "__file__" 是没有意义的。 - davidlatwe
29
为什么这个回答有赞?很多人选择了它,可能是因为它解决了一个未处理的异常,所以他们认为它是正确的吗? 但是这不是一个正确的解决方案。实际上,它只是假设存在一个名为“__file__”的文件,并在其前面添加一个文件夹的名称(如果该文件夹存在) - Todd
3
这显然是有效的,因为iPython无法找到os.path.dirname(os.path.abspath(os.getcwd() + "\_file_"))并将其缩短为os.getcwd() - Rustam A.
这段代码没有在相同的上下文中进行测试...这就是为什么它没有产生相同的错误的原因。 - RexBarker

15

如果您将代码放在.py文件中,请使用:os.path.abspath(__file__)

如果您直接在脚本或者Jupyter Notebook中使用代码,请将文件名用双引号括起来:os.path.abspath("__file__")


你的答案可以通过添加额外的支持信息来改进。请[编辑]以添加更多细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community

10

fd = os.path.dirname(os.path.realpath(file)) 会打印出 .../../folder1/,但是 cwd = os.path.dirname(os.path.realpath(sys.argv[0]))。
print cwd 会打印出 ../../。
- bruceparker
8
这将提供启动 shell 的二进制 Python 的路径,而不是当前工作目录。 - hobs
1
应该使用 argv[1] 而不是 argv[0] - plustar

9
如果您只想获取当前工作目录,os.getcwd()将会给您与os.path.dirname(__file__)相同的结果,只要您在代码中没有改变工作目录。在交互模式下,os.getcwd()也可以使用。
因此,os.path.join(os.path.dirname(__file__))变成了os.path.join(os.getcwd())

这是一个赢家。 - Shawn
7
这个答案不正确。os.path.dirname(__file__)os.getcwd()报告的不是同样的东西。它会给你文件的目录名。如果这恰好与os.getcwd()匹配,那只是巧合而已。 - Todd

7

如果您在Python shell中运行命令,则会得到以下结果:

>>> __file__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name '__file__' is not defined

您需要直接执行该文件,通过将其作为参数传递给python命令:

$ python somefile.py

在您的情况下,应该使用 python setup.py install 进行安装。

3
如果您正在通过命令行执行文件,您可以使用这个技巧。
import traceback

def get_this_filename():
    try:
        raise NotImplementedError("No error")
    except Exception as e:
        exc_type, exc_value, exc_traceback = sys.exc_info()
        filename = traceback.extract_tb(exc_traceback)[-1].filename
    return filename

在UnrealEnginePython控制台中,通过调用py.exec myfile.py实现了我的需求。


1
如果您正在使用Jupyter Notebook,可以这样写:
MODEL_NAME = os.path.basename(文件)[:-3]
其中的“文件”是指具体的文件名。
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-10-f391bbbab00d> in <module>
----> 1 MODEL_NAME = os.path.basename(__file__)[:-3]

NameError: name '__file__' is not defined

你应该像这样在前面放置一个 ' ! '。
!MODEL_NAME = os.path.basename(__file__)[:-3]

/bin/bash: -c: line 0: syntax error near unexpected token `('
/bin/bash: -c: line 0: `MODEL_NAME = os.path.basename(__file__)[:-3]'

完成.....


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接