python NameError: глобальное имя '__file__' не определено

112

Когда я запускаю этот код в 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']
      )
Кайбин Ян
источник

Ответы:

134

Эта ошибка возникает, когда вы добавляете эту строку os.path.join(os.path.dirname(__file__))в интерактивную оболочку python.

Python Shellне определяет текущий путь к файлу, __file__и это связано с тем, filepathв котором вы добавили эту строку

Так что вы должны вписать эту строку os.path.join(os.path.dirname(__file__))в file.py. а затем запустите python file.py, он работает, потому что он принимает ваш путь к файлу.

Nilesh
источник
8
именно мой опыт. но как заставить его работать в оболочке?
s2t2
1
Но для запуска file.pyиз сценария вы должны поместить его, например, в тот же каталог, что и ваш сценарий. Таким образом, вам нужно перейти в этот каталог перед запуском file.py... Так что все еще ищется что-то получше.
ztyh
Итак, Emacs использует интерактивную оболочку, когда вы Cc Cp? Python-оболочки. Есть ли способ использовать эту оболочку, как если бы это был терминал, запускающий файл? Есть 3 варианта запуска оболочки: CMD DEDICATED SHOW Может ли один из них сделать это?
sinekonata
18

У меня была такая же проблема с PyInstaller и Py2exe, поэтому я наткнулся на разрешение в FAQ от 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
Kwuite
источник
11

измените свои коды следующим образом! меня устраивает. `

os.path.dirname(os.path.abspath("__file__"))
Jojo Josiane
источник
7
Я думаю, что вы действительно используете os.getcwd(), согласно документу , и "__file__"это бессмысленно.
Давидлатве
5
Почему у него есть положительные голоса? Что многие люди взяли это, и, поскольку это избавило от необработанного исключения, они решили, что это правильно ?? Это неправильное решение, люди . Он говорит, что у вас есть файл с буквальным названием " __file__" и вы добавляете, в какой папке он мог бы быть, если бы он существовал!
Тодд
11

Я сталкивался со случаями, когда __file__не работал должным образом. Но пока меня не подвело:

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

Это ближе всего к аналогу Python в C - х __FILE__.

Поведение Python __file__сильно отличается от C__FILE__ . Версия C предоставит вам исходный путь к исходному файлу. Это полезно для регистрации ошибок и определения того, в каком исходном файле есть ошибка.

Python __file__дает вам только имя текущего исполняемого файла, что может быть не очень полезно при выводе журнала.

Тодд
источник
2
Это работает также, когда python встроен в другое приложение
sdaau
Мне больше повезло с этим, чем с os.path.dirname(os.path.realpath(...))методом.
Mr. S
1
Это должен быть главный ответ.
183.amir
9

Вы пользуетесь интерактивным переводчиком? Ты можешь использовать

sys.argv[0]

Вы должны прочитать: Как мне получить путь к текущему исполняемому файлу в Python?

Элоимс
источник
fd = os.path.dirname (os.path.realpath ( file )) и его распечатка напечатала ... / .. / folder1 / но cwd = os.path.dirname (os.path.realpath (sys.argv [0 ])) >>> print cwd printts ../../
bruceparker
7
это даст путь к двоичному питону, запустившему оболочку, а НЕ текущий рабочий каталог
hobs
это должно быть argv[1]вместоargv[0]
plustar
8

Я решил это, обработав файл как строку, то есть поставил "__file__"(вместе с кавычками!) Вместо__file__

У меня это отлично работает:

wk_dir = os.path.dirname(os.path.realpath('__file__'))
lsheng
источник
8
Это действительно работает, но я не могу понять, почему. Почему "__file__"между кавычками обрабатывается иначе, чем __file__без кавычек?
Gio
5
Потому что он не ссылается на отсутствующую глобальную переменную. Вместо этого он рассматривает строку « файл » как часть пути.
JoshVarty
42
Это не возвращает каталог, в котором находится файл , а просто возвращает текущий рабочий каталог (где вызывается python). -1
Xiangyu
8
Любое имя файла подойдет вместо "__file__". Напр realpath('nonexistentfile.whatever').
hobs
35
Этот ответ действительно следует удалить, поскольку он неверен и вводит в заблуждение. Тот факт, что за него так высоко проголосовали, довольно тревожит ...
Cas
7

Если все, что вам нужно, это получить текущий рабочий каталог, os.getcwd()это даст вам то же самое, os.path.dirname(__file__)если вы не изменили рабочий каталог где-либо еще в своем коде. os.getcwd()также работает в интерактивном режиме.

Так os.path.join(os.path.dirname(__file__)) становится os.path.join(os.getcwd())

Эндрю Фоллгрен
источник
Это победитель
Шон
1
Ответ на этот вопрос не является правильным . os.path.dirname(__file__)не сообщает о том же, что и os.getcwd(). Это дает вам имя каталога файла. Если это окажется совпадением, os.getcwd()это просто совпадение.
Тодд,
4

Вы получите это, если запускаете команды из оболочки Python:

>>> __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

Бурхан Халид
источник
2

Что вы можете сделать, так это использовать следующие

import os
if '__file__' in vars():
    wk_dir = os.path.dirname(os.path.realpath('__file__'))
else:
    print('We are running the script interactively')

Обратите внимание, что использование строки '__file__'действительно относится к фактической переменной__file__ . Вы, конечно, можете проверить это сами ..

Дополнительным бонусом этого решения является гибкость, когда вы запускаете сценарий частично в интерактивном режиме (например, для его тестирования / разработки) и можете запускать его через командную строку.

zwep
источник
Что касается вашего примечания, то '__file__'пока - допустимое имя переменной, и ваше ifусловие будет истинным, os.path.realpath('__file__')вернет поддельный путь, обрабатываемый так, '__file__'как если бы это было имя файла. Если все, что вам нужно, это его родительский каталог os.path.dirname(), все в порядке, но это «взлом». @zwep
Тодд
Также при ссылке __file__из исходного файла будет получен путь к файлу, в котором он используется - это не то же самое, что os.getcwd(). Это не всегда будет ваш wk_dir- или рабочий каталог.
Тодд,
2

Если вы запускаете файл через командную строку, вы можете использовать этот прием

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

crizCraig
источник
1

У меня была такая же проблема в ноутбуке Jupyter. Пока я использовал os.path.split (os.path.realpath ( file )), записная книжка выдавала ошибку.

Поэтому я использовал слово « файл ». Это сработало отлично.

Анкит каушик
источник
0

У меня точно такая же проблема, и я использую, вероятно, тот же учебник . Определение функции:

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

глючит, так os.path.dirname(__file__)как не вернет то, что нужно. Попробуйте заменить os.path.dirname(__file__)на os.path.dirname(os.path.abspath(__file__)):

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

Я только что написал Эндрю, что фрагмент кода в текущей документации не работает, надеюсь, он будет исправлен.

Ducin
источник