python NameError: nazwa globalna „__file__” nie jest zdefiniowana

112

Kiedy uruchamiam ten kod w Pythonie 2.7, pojawia się ten błąd:

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

kod to:

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='[email protected]',
    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']
      )
Kaibing Yang
źródło

Odpowiedzi:

134

Ten błąd pojawia się, gdy dodajesz ten wiersz os.path.join(os.path.dirname(__file__))w powłoce interaktywnej Pythona.

Python Shellnie wykrywa bieżącej ścieżki do pliku w programie __file__i jest powiązana z tym, filepathw którym dodałeś ten wiersz

Więc trzeba napisać ten wiersz os.path.join(os.path.dirname(__file__))w file.py. a następnie uruchom python file.py, działa, ponieważ pobiera ścieżkę do pliku.

Nilesh
źródło
8
dokładnie moje doświadczenie. ale jak sprawić, by działał w powłoce?
s2t2
1
Ale aby uruchomić file.pyze skryptu, umieściłbyś go na przykład w tym samym katalogu, co skrypt. Więc musisz przejść do tego katalogu przed uruchomieniem file.py... Więc wciąż szuka się czegoś lepszego.
ztyh
Więc Emacs używa interaktywnej powłoki podczas Cc Cp? python-shell. Czy istnieje sposób na użycie tej powłoki tak, jakby był to terminal uruchamiający plik? Istnieją 3 opcje uruchomienia powłoki: POKAZ DEDYKOWANY CMD Czy któryś z nich to zrobi?
sinekonata
18

Miałem ten sam problem z PyInstaller i Py2exe, więc natknąłem się na rozwiązanie w FAQ od cx-freeze.

Podczas korzystania ze skryptu z konsoli lub jako aplikacji funkcje opisane poniżej dostarczą „ścieżkę wykonywania”, a nie „rzeczywistą ścieżkę do pliku”:

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

Źródło:
http://cx-freeze.readthedocs.org/en/latest/faq.html

Twoja stara linia (pytanie wstępne):

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

Zastąp wiersz kodu następującym fragmentem.

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)

Za pomocą powyższego kodu możesz dodać aplikację do ścieżki swojego systemu operacyjnego, możesz ją uruchomić w dowolnym miejscu bez problemu, że Twoja aplikacja nie może znaleźć swoich plików danych / konfiguracyjnych.

Przetestowano w Pythonie:

  • 3.3.4
  • 2.7.13
Kwuite
źródło
12

zmień swoje kody w następujący sposób! mi to pasuje. `

os.path.dirname(os.path.abspath("__file__"))
Jojo Josiane
źródło
7
Myślę, że faktycznie używasz os.getcwd(), według doktora , i "__file__"jest bez znaczenia.
davidlatwe
5
Dlaczego to ma pozytywne głosy? Tak wiele osób to zrobiło, a ponieważ pozbyło się nieobsługiwanego wyjątku, założyli, że to prawda? To nie jest właściwe rozwiązanie, ludzie . To, co robi, to powiedzenie, że masz plik o nazwie dosłownie „ __file__” i dodajesz na początku folder, w którym mógłby się on znajdować, gdyby istniał!
Todd
11

Napotkałem przypadki, w których __file__nie działa zgodnie z oczekiwaniami. Ale jak dotąd nie zawiodły mnie:

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

Jest to najbliższa rzecz do analogu Python C użytkownika __FILE__.

Zachowanie Pythona __file__jest znacznie różni się od C użytkownika __FILE__. Wersja C poda oryginalną ścieżkę do pliku źródłowego. Jest to przydatne w rejestrowaniu błędów i sprawdzaniu, który plik źródłowy zawiera błąd.

Python __file__podaje tylko nazwę aktualnie wykonywanego pliku, co może nie być zbyt przydatne w danych wyjściowych dziennika.

Todd
źródło
2
Działa to również wtedy, gdy Python jest osadzony w innej aplikacji
sdaau
Miałem więcej szczęścia z tym niż z os.path.dirname(os.path.realpath(...))metodą.
Pan S
1
To powinna być najlepsza odpowiedź.
183.amir
9

Czy korzystasz z interaktywnego tłumacza? Możesz użyć

sys.argv[0]

Powinieneś przeczytać: Jak uzyskać ścieżkę do aktualnie wykonywanego pliku w Pythonie?

Eloims
źródło
fd = os.path.dirname (os.path.realpath ( file )) i drukuje to wydrukowane ... / .. / folder1 / ale cwd = os.path.dirname (os.path.realpath (sys.argv [0 ])) >>> drukuj wydruki cwd ../../
bruceparker
7
to da ścieżkę do binarnego Pythona, który uruchomił powłokę, a NIE bieżącego katalogu roboczego
płyty grzewcze
powinno być argv[1]zamiastargv[0]
plustar
9

Rozwiązałem to, traktując plik jako ciąg znaków, tj. Wstawiając "__file__"(razem z cudzysłowami!) Zamiast__file__

To działa dobrze dla mnie:

wk_dir = os.path.dirname(os.path.realpath('__file__'))
lsheng
źródło
8
To rzeczywiście działa, ale nie wiem, dlaczego. Dlaczego "__file__"między cudzysłowami są traktowane inaczej niż __file__bez cudzysłowów?
Gio,
5
Ponieważ nie odnosi się do brakującej zmiennej globalnej. Zamiast tego traktuje ciąg „ plik ” jako część ścieżki.
JoshVarty,
42
To nie zwraca katalogu, w którym znajduje się plik , ale po prostu zwraca bieżący katalog roboczy (gdzie wywoływany jest python). -1
Xiangyu
8
Dowolna nazwa pliku będzie zastępować "__file__". Np realpath('nonexistentfile.whatever').
płyty kuchenne
35
Ta odpowiedź naprawdę powinna zostać usunięta, ponieważ jest niepoprawna i myląca. Fakt, że jest tak wysoko oceniany, jest raczej niepokojący ...
Cas
6

Jeśli wszystko, czego szukasz, to pobranie bieżącego katalogu roboczego os.getcwd(), da ci to samo, os.path.dirname(__file__)o ile nie zmienisz katalogu roboczego w innym miejscu w kodzie. os.getcwd()działa również w trybie interaktywnym.

Tak os.path.join(os.path.dirname(__file__)) się stanie os.path.join(os.getcwd())

Andrew Fallgren
źródło
To jest zwycięzca
Shawn
1
Ta odpowiedź jest nieprawidłowa . os.path.dirname(__file__)nie zgłasza tego samego co os.getcwd(). To, co daje, to nazwa katalogu pliku. Jeśli okaże się, że os.getcwd()to pasuje, to tylko zbieg okoliczności.
Todd
4

Otrzymasz to, jeśli uruchamiasz polecenia z powłoki Pythona:

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

Musisz wykonać plik bezpośrednio, przekazując go jako argument do pythonpolecenia:

$ python somefile.py

W twoim przypadku tak powinno być python setup.py install

Burhan Khalid
źródło
2

Co możesz zrobić, to użyć następujących

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

Zauważ tutaj, że użycie łańcucha '__file__'rzeczywiście odnosi się do rzeczywistej zmiennej __file__. Oczywiście możesz to sprawdzić samodzielnie.

Dodatkową zaletą tego rozwiązania jest elastyczność, gdy uruchamiasz skrypt częściowo interaktywnie (np. Aby go przetestować / opracować) i możesz go uruchomić za pomocą wiersza poleceń

zwep
źródło
Jeśli chodzi o twoją notatkę, while '__file__'jest prawidłową nazwą zmiennej, a twój ifwarunek będzie prawdziwy, os.path.realpath('__file__')zwróci fałszywą ścieżkę, traktując ją '__file__'tak, jakby była to nazwa pliku. Jeśli wszystko, czego potrzebujesz, to jego katalog nadrzędny przez os.path.dirname(), wszystko w porządku - ale to „hack”. @zwep
Todd
Również odwołanie __file__z pliku źródłowego spowoduje pobranie ścieżki do pliku, w którym jest używany - to nie to samo, co os.getcwd(). Nie zawsze będzie to Twój wk_dir- lub katalog roboczy.
Todd
2

Jeśli wykonujesz plik za pomocą wiersza poleceń, możesz użyć tego hacka

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

To zadziałało dla mnie w konsoli UnrealEnginePython, wywołując py.exec myfile.py

crizCraig
źródło
1

Miałem ten sam problem w notatniku Jupyter. Podczas gdy użyłem „os.path.split (os.path.realpath ( plik ))”, notatnik zgłosił błąd.

Dlatego użyłem „ pliku ”. Działało idealnie.

Ankit kaushik
źródło
0

Mam dokładnie ten sam problem i używam prawdopodobnie tego samego samouczka . Definicja funkcji:

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

jest wadliwy, ponieważ os.path.dirname(__file__)nie zwróci tego, czego potrzebujesz. Spróbuj wymienić os.path.dirname(__file__)z os.path.dirname(os.path.abspath(__file__)):

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

Właśnie wysłałem Andrew, że fragment kodu w bieżących dokumentach nie działa, mam nadzieję, że zostanie poprawiony.

ducin
źródło