python NameError: nama global '__file__' tidak ditentukan

112

Ketika saya menjalankan kode ini di python 2.7, saya mendapatkan kesalahan ini:

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

kodenya adalah:

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
sumber

Jawaban:

134

Kesalahan ini terjadi saat Anda menambahkan baris ini os.path.join(os.path.dirname(__file__))di shell interaktif python.

Python Shelltidak mendeteksi jalur file saat ini di __file__dan ini terkait dengan Anda filepathdi mana Anda menambahkan baris ini

Jadi, Anda harus menulis baris ini os.path.join(os.path.dirname(__file__))di file.py. dan kemudian jalankan python file.py, Ia bekerja karena ia mengambil jalur file Anda.

Nilesh
sumber
8
persis pengalaman saya. tapi bagaimana cara membuatnya bekerja di dalam shell?
s2t2
1
Tetapi untuk menjalankan file.pydari skrip, Anda akan meletakkannya di direktori yang sama dengan skrip Anda misalnya. Jadi, Anda harus pindah ke direktori ini sebelum menjalankan file.py... Jadi, masih ada yang lebih baik yang dicari.
ztyh
Jadi Emacs menggunakan shell interaktif saat Anda Cc Cp? python-shell. Apakah ada cara untuk menggunakan shell ini seolah-olah itu adalah terminal yang menjalankan file? Ada 3 pilihan untuk menjalankan shell: CMD DEDICATED SHOW Apakah salah satu dari mereka melakukan ini?
sinekonata
18

Saya memiliki masalah yang sama dengan PyInstaller dan Py2exe, jadi saya menemukan resolusi di FAQ dari cx-freeze.

Saat menggunakan skrip Anda dari konsol atau sebagai aplikasi, fungsi di bawah ini akan memberikan Anda "jalur eksekusi", bukan "jalur file aktual":

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

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

Baris lama Anda (pertanyaan awal):

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

Gantikan baris kode Anda dengan cuplikan berikut.

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)

Dengan kode di atas Anda dapat menambahkan aplikasi Anda ke jalur os Anda, Anda dapat menjalankannya di mana saja tanpa masalah bahwa aplikasi Anda tidak dapat menemukan file data / konfigurasinya.

Diuji dengan python:

  • 3.3.4
  • 2.7.13
Kwuite
sumber
12

ubah kode Anda sebagai berikut! itu berhasil untuk saya. `

os.path.dirname(os.path.abspath("__file__"))
Jojo Josiane
sumber
7
Saya pikir Anda benar-benar menggunakan os.getcwd(), menurut doc , dan "__file__"itu tidak ada artinya.
davidlatwe
5
Mengapa ini memiliki suara positif? Banyak orang yang mengambil ini, dan karena itu menghilangkan pengecualian yang tidak tertangani, mereka menganggap itu benar ?? Ini bukan solusi yang tepat orang . Apa yang dilakukannya adalah mengatakan bahwa Anda memiliki sebuah file bernama secara harfiah, " __file__" dan Anda menambahkan folder apa yang mungkin ada di dalamnya jika ada!
Todd
11

Saya telah mengalami kasus di mana __file__tidak berfungsi seperti yang diharapkan. Tetapi hal berikut ini tidak mengecewakan saya sejauh ini:

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

Ini adalah hal yang paling dekat analog Python untuk C __FILE__.

Perilaku Python __file__jauh berbeda dari C __FILE__. Versi C akan memberi Anda jalur asli dari file sumber. Ini berguna untuk mencatat kesalahan dan mengetahui file sumber mana yang memiliki bug.

Python __file__hanya memberi Anda nama file yang saat ini dijalankan, yang mungkin tidak terlalu berguna dalam output log.

Todd
sumber
2
Ini berfungsi juga ketika python disematkan di aplikasi lain
sdaau
Saya lebih beruntung dengan ini daripada os.path.dirname(os.path.realpath(...))metodenya.
Tn. S
1
Ini harus menjadi jawaban teratas.
183.amir
9

Apakah Anda menggunakan penerjemah interaktif? Kamu bisa memakai

sys.argv[0]

Anda harus membaca: Bagaimana cara mendapatkan jalur dari file yang dieksekusi saat ini dengan Python?

Eloims
sumber
fd = os.path.dirname (os.path.realpath ( file )) dan mencetaknya dicetak ... / .. / folder1 / tetapi cwd = os.path.dirname (os.path.realpath (sys.argv [0 ])) >>> mencetak cetakan
cwd ../../
7
ini akan memberikan jalur ke python biner yang meluncurkan shell, BUKAN direktori kerja saat ini
hobs
itu harus argv[1]bukannyaargv[0]
plustar
9

Saya menyelesaikannya dengan memperlakukan file sebagai string, yaitu menempatkan "__file__"(bersama dengan tanda kutip!), Bukan__file__

Ini berfungsi dengan baik untuk saya:

wk_dir = os.path.dirname(os.path.realpath('__file__'))
lsheng
sumber
8
Ini memang berhasil, tetapi saya tidak bisa memikirkan mengapa. Mengapa di "__file__"antara tanda kutip diperlakukan berbeda dengan __file__tanpa tanda kutip?
Gio
5
Karena tidak mereferensikan variabel global yang hilang. Sebaliknya itu memperlakukan string ' file ' sebagai bagian dari jalur.
JoshVarty
42
Ini tidak mengembalikan direktori tempat file berada, tetapi hanya mengembalikan direktori kerja saat ini (tempat python dipanggil). -1
Xiangyu
8
Nama file apa pun bisa menggantikan "__file__". Mis realpath('nonexistentfile.whatever').
kompor
35
Jawaban ini benar-benar harus dihapus karena salah dan menyesatkan. Fakta bahwa itu adalah suara positif yang sangat tinggi agak mengkhawatirkan ...
Cas
6

Jika semua yang Anda cari adalah untuk mendapatkan direktori kerja Anda saat ini os.getcwd()akan memberikan Anda hal yang sama os.path.dirname(__file__)selama Anda belum mengubah direktori kerja di tempat lain dalam kode Anda. os.getcwd()juga bekerja dalam mode interaktif.

Jadi os.path.join(os.path.dirname(__file__)) jadilah os.path.join(os.getcwd())

Andrew Fallgren
sumber
Ini adalah pemenang
Shawn
1
Jawaban ini tidak benar . os.path.dirname(__file__)tidak melaporkan hal yang sama seperti os.getcwd(). Apa yang diberikannya adalah nama dir dari file tersebut. Jika itu ternyata cocok, os.getcwd()itu hanya kebetulan.
Todd
4

Anda akan mendapatkan ini jika Anda menjalankan perintah dari shell python:

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

Anda perlu menjalankan file secara langsung, dengan meneruskannya sebagai argumen ke pythonperintah:

$ python somefile.py

Dalam kasus Anda, seharusnya begitu python setup.py install

Burhan Khalid
sumber
2

Yang dapat Anda lakukan adalah menggunakan yang berikut ini

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

Perhatikan di sini bahwa menggunakan string '__file__'memang mengacu pada variabel sebenarnya __file__. Tentu saja Anda dapat mengujinya sendiri ..

Bonus tambahan dari solusi ini adalah fleksibilitas ketika Anda menjalankan skrip sebagian secara interaktif (misalnya untuk menguji / mengembangkannya), dan dapat menjalankannya melalui baris perintah

zwep
sumber
Mengenai catatan Anda, while '__file__'adalah nama variabel yang valid, dan ifkondisi Anda akan benar, os.path.realpath('__file__')akan mengembalikan jalur palsu yang memperlakukan '__file__'seolah-olah itu adalah nama file. Jika yang Anda butuhkan hanyalah melalui direktori induknya os.path.dirname(), Anda baik-baik saja - tetapi itu adalah "retas". @zwep
Todd
Juga mereferensikan __file__dari dalam file sumber akan mendapatkan jalur dari file yang digunakan di dalamnya - ini tidak sama dengan os.getcwd(). Ini tidak akan selalu menjadi wk_dir- atau direktori kerja Anda.
Todd
2

Jika Anda menjalankan file melalui baris perintah, Anda dapat menggunakan peretasan ini

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

Ini bekerja untuk saya di konsol UnrealEnginePython, menelepon py.exec myfile.py

crizCraig.dll
sumber
1

Saya memiliki masalah yang sama di notebook Jupyter. Saat saya menggunakan 'os.path.split (os.path.realpath ( file ))', notebook mengalami kesalahan.

Jadi saya menggunakan ' file '. Ini bekerja dengan sempurna.

Ankit kaushik
sumber
0

Saya mengalami masalah yang persis sama dan mungkin menggunakan tutorial yang sama . Definisi fungsi:

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

adalah buggy, karena os.path.dirname(__file__)tidak akan mengembalikan apa yang Anda butuhkan. Coba ganti os.path.dirname(__file__)dengan os.path.dirname(os.path.abspath(__file__)):

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

Saya baru saja memposting Andrew bahwa potongan kode di dokumen saat ini tidak berfungsi, mudah-mudahan, ini akan diperbaiki.

ducin
sumber