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Це працює, тому що займає ваш шлях.


8
саме мій досвід. але як змусити його працювати в оболонці?
s2t2

1
Але для запуску file.pyзі сценарію, ви б помістили його в той самий каталог, що і ваш сценарій, наприклад. Тож вам потрібно перейти до цього каталогу перед запуском file.py... Тож все-таки шукається щось краще.
зтих

Отже, Emacs використовує інтерактивну оболонку, коли ви використовуєте Cc Cp? пітон-оболонка. Чи є спосіб використовувати цю оболонку так, ніби це термінал, на якому працює файл? Існує 3 варіанти запуску оболонки: CMD DEDICATED SHOW Один із них зробив би це?
sinekonata

18

У мене була така ж проблема з 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

12

змінити свої коди так! це працює для мене. `

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

7
Я думаю, ви насправді використовуєте os.getcwd(), на думку doc , і "__file__"безглуздо.
davidlatwe

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(...))методом.
Містер S

1
Це має бути головна відповідь.
183.амір

9

Чи використовуєте ви інтерактивного перекладача? Можна використовувати

sys.argv[0]

Ви повинні прочитати: Як отримати шлях до поточного виконаного файлу в Python?


fd = os.path.dirname (os.path.realpath ( файл )) друкуючи його надрукованим ... / .. / folder1 /, але cwd = os.path.dirname (os.path.realpath (sys.argv [0 ])) >>> друкуйте роздруківки cwd ../../
bruceparker

7
це дасть шлях до бінарного пітона, який запустив оболонку, а не поточного робочого каталогу
варильних

це має бути argv[1]замістьargv[0]
плюстар

9

Я вирішив це, розглядаючи файл як рядок, тобто ставив "__file__"(разом із цитатами!) Замість__file__

Це добре для мене:

wk_dir = os.path.dirname(os.path.realpath('__file__'))

8
Це справді працює, але я не можу зрозуміти чому. Чому "__file__"між цитатами трактується інше, ніж __file__без лапок?
Gio

5
Тому що він не посилається на відсутніх глобальних змінних. Натомість він розглядає рядок " файл " як частину шляху.
JoshVarty

42
Це не повертає каталог, де знаходиться файл , а просто повертає поточну робочу директорію (де називається python). -1
Xiangyu

8
Будь-яке ім'я файлу буде робити замість "__file__". Напр realpath('nonexistentfile.whatever').
варильні панелі

35
Цю відповідь дійсно слід усунути, оскільки вона є невірною та оманливою. Факт, на який його високо оцінюють, досить хвилює ...
Cas

6

Якщо все, що ви шукаєте, - це отримати ваш поточний робочий каталог 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(). Що це дає вам, це ім'я файлу dir. Якщо це виявиться збігом, 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__. Ви можете перевірити це, звичайно, самі.

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


Що стосується вашої примітки, хоча '__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


1

У мене була така ж проблема в зошиті Юпітера. Поки я використовував 'os.path.split (os.path.realpath ( файл ))', ноутбук видав помилку.

Таким чином я використав " файл ". Це спрацювало чудово.


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()

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.