Python 3.2: " Exception NameError: NameError("global name '__file__' is not defined",)"
sdaau
20
@daau: __file__tidak didefinisikan dalam interpreter interaktif, karena tidak ada artinya di sana. Ini diatur oleh implementasi impor, jadi jika Anda menggunakan mekanisme impor non-standar mungkin juga tidak disetel.
Sven Marnach
8
Setidaknya untuk Python 2.7, saya percaya import osdiperlukan untuk ini untuk bekerja. Saya akan menambahkan ini ke dalam jawabannya.
@ sven-marnach: Oh, Anda benar . Saya telah Melakukannya Salah selama bertahun-tahun!
cdunn2001
136
import sys
print sys.argv[0]
Ini akan mencetak foo.pyuntuk python foo.py, dir/foo.pyuntuk python dir/foo.py, dll. Ini adalah argumen pertama python. (Perhatikan bahwa setelah py2exe, itu akan menjadi foo.exe.)
@DenisMalinovsky: tentukan "tidak akan bekerja". Jika Anda menelepon python linkfile.py, di mana linkfile.pysymlink ke realfile.py, sys.argv[0]akan 'linkfile.py', yang mungkin atau mungkin tidak apa yang Anda inginkan; tentu saja itu yang saya harapkan . __file__adalah sama: itu akan terjadi linkfile.py. Jika Anda ingin mencari 'realfile.py'dari 'linkfile.py', coba os.path.realpath('linkfile.py').
Chris Morgan
6
+1 karena (a) sedikit lebih rapi dan (b) masih akan berfungsi dalam modul (di mana variabel file akan menjadi file modul, bukan yang dieksekusi).
robert
Jawaban ini bagus karena berfungsi di IDLE juga. Sebagai catatan, untuk mendapatkan hanya nama file, Anda dapat menulis os.path.basename (sys.argv [0])
Steven Bluen
Lebih penting lagi, ini tidak berfungsi kecuali dari dalam file utama. Jangan gunakan ini, gunakan __file__saja.
Apollys mendukung Monica
APA!!! Apakah Anda pernah mencoba ini? Justru sebaliknya yang benar. Penanya menanyakan nama skrip python yang sedang berjalan - bukan file python yang sedang dieksekusi. Bayangkan Anda memiliki skrip yang, ketika terjadi kesalahan, mencetak nama skrip beserta argumen yang dibolehkan. Anda menempatkannya dalam suatu fungsi, menggunakan salah satu dari 2 teknik ini. Pada titik tertentu, Anda memutuskan untuk memindahkan fungsi ke perpustakaan eksternal. Apakah Anda ingin mencetak nama skrip utama yang sedang berjalan, atau nama file perpustakaan yang sedang dieksekusi?
John Deighan
71
Demi kelengkapan, saya pikir akan bermanfaat untuk merangkum berbagai hasil yang mungkin dan menyediakan referensi untuk perilaku yang tepat dari masing-masing:
__file__adalah file yang sedang dieksekusi, sebagaimana dirinci dalam dokumentasi resmi :
__file__adalah pathname dari file dari mana modul dimuat, jika itu diambil dari file. The __file__atribut mungkin hilang untuk beberapa jenis modul, seperti C modul yang statis terhubung ke penafsir; untuk modul ekstensi yang dimuat secara dinamis dari perpustakaan bersama, itu adalah nama path dari file perpustakaan bersama.
Dari Python3.4 dan seterusnya, per masalah 18416 , __file__selalu merupakan jalur absolut, kecuali jika file yang sedang dieksekusi adalah skrip yang telah dieksekusi secara langsung (bukan melalui penerjemah dengan -mopsi baris perintah) menggunakan jalur relatif.
__main__.__file__(memerlukan pengimporan __main__) dengan mudah mengakses __file__atribut modul utama yang disebutkan di atas , misalnya skrip yang dipanggil dari baris perintah.
sys.argv[0](wajib mengimpor sys) adalah nama skrip yang dipanggil dari baris perintah, dan mungkin merupakan jalur absolut, sebagaimana dirinci dalam dokumentasi resmi :
argv[0]adalah nama skrip (tergantung pada sistem operasi apakah ini nama path lengkap atau tidak). Jika perintah dieksekusi menggunakan -copsi baris perintah ke interpreter, argv[0]diatur ke string '-c'. Jika tidak ada nama skrip yang diteruskan ke interpreter Python, argv[0]adalah string kosong.
Seperti disebutkan dalam jawaban lain untuk pertanyaan ini , skrip Python yang dikonversi menjadi program yang dapat dieksekusi yang berdiri sendiri melalui alat-alat seperti py2exe atau PyInstaller mungkin tidak menampilkan hasil yang diinginkan ketika menggunakan pendekatan ini (yaitu sys.argv[0]akan menyimpan nama yang dapat dieksekusi daripada nama dari file Python utama dalam executable itu).
Jika tidak ada opsi yang disebutkan di atas yang berfungsi, mungkin karena operasi impor yang tidak teratur, modul inspeksi mungkin terbukti bermanfaat. Secara khusus, memohon inspect.getfile(...)pada inspect.currentframe()bisa bekerja, meskipun yang terakhir akan kembaliNone ketika berjalan di sebuah implementasi tanpa Python stack frame.
Menangani tautan simbolis
Jika skrip saat ini adalah tautan simbolik, maka semua yang di atas akan mengembalikan jalur tautan simbolik daripada path file asli dan os.path.realpath(...)harus dipanggil untuk mengekstrak yang terakhir.
Manipulasi lebih lanjut yang mengekstrak nama file yang sebenarnya
os.path.basename(...)dapat dipanggil pada salah satu di atas untuk mengekstrak nama file yang sebenarnya dan os.path.splitext(...)dapat dipanggil pada nama file yang sebenarnya untuk memotong sufiksnya, seperti padaos.path.splitext(os.path.basename(...)) .
Catatan yang __file__akan memberikan file tempat kode ini berada, yang dapat diimpor dan berbeda dari file utama yang ditafsirkan. Untuk mendapatkan file utama, modul __main__ khusus dapat digunakan:
import __main__ as main
print(main.__file__)
Catatan yang __main__.__file__berfungsi di Python 2.7 tetapi tidak di 3.2, jadi gunakan sintaks import-as seperti di atas untuk membuatnya portabel.
Ini berfungsi dalam banyak kasus tetapi tidak ketika saya menggunakan rPythonpaket dari Rbahasa. Itu pasti kasus luar biasa yang terlalu sulit untuk ditangani.
Leonid
Memang, paket rPython menanamkan interpreter python, yang berarti tidak ada file 'utama' seperti ada ketika python berjalan sendiri (Anda akan menemukan perilaku yang sama kapan saja python disematkan). Itu mengimpor secara __main__internal, untuk digunakan dalam melewati variabel antara Rdan python, jadi itu akan relatif mudah untuk membuatnya ditetapkan __main__.__file__sebelum memanggil yang lain, tapi saya bahkan tidak yakin apa yang akan menjadi nilai yang sesuai dalam kasus ini.
Perkins
42
Jawaban di atas baik. Tetapi saya menemukan metode ini lebih efisien menggunakan hasil di atas.
Ini menghasilkan nama file skrip aktual bukan jalur.
import sys
import os
file_name = os.path.basename(sys.argv[0])
semua jawaban itu bagus, tetapi memiliki beberapa masalah Anda mungkin tidak melihat pada pandangan pertama.
mari tentukan apa yang kita inginkan - kita ingin nama skrip yang dieksekusi, bukan nama modul saat ini - jadi __file__hanya akan berfungsi jika digunakan pada skrip yang dieksekusi, bukan dalam modul yang diimpor.
sys.argvjuga dipertanyakan - bagaimana jika program Anda dipanggil oleh pytest? atau pydoc runner? atau apakah itu disebut oleh uwsgi?
dan - ada metode ketiga untuk mendapatkan nama skrip, saya belum melihat dalam jawaban - Anda dapat memeriksa tumpukan.
Masalah lain adalah, bahwa Anda (atau program lain) dapat mengutak-atik sys.argvdan__main__.__file__ - mungkin ada, mungkin tidak. Mungkin valid, atau tidak. Setidaknya Anda dapat memeriksa apakah skrip (hasil yang diinginkan) ada!
bitranox perpustakaan saya / lib_programname di github melakukan hal itu:
periksa apakah __main__ada
periksa apakah __main__.__file__ada
memang memberikan __main__.__file__hasil yang valid (apakah skrip itu ada?)
jika tidak: periksa sys.argv:
apakah ada pytest, docrunner, dll di sys.argv? -> jika ya, abaikan itu
bisakah kita mendapatkan hasil yang valid di sini?
jika tidak: periksa tumpukan dan dapatkan hasilnya dari sana
jika juga stack tidak memberikan hasil yang valid, maka lemparkan Exception.
dengan cara itu, solusi saya bekerja sejauh ini dengan setup.py test, uwsgi, pytest, pycharm pytest, pycharm docrunner (doctest), dreampie,eclipse
ada juga artikel blog yang bagus tentang masalah itu dari Dough Hellman, "Menentukan Nama Proses dari Python"
Exception NameError: NameError("global name '__file__' is not defined",)
"__file__
tidak didefinisikan dalam interpreter interaktif, karena tidak ada artinya di sana. Ini diatur oleh implementasi impor, jadi jika Anda menggunakan mekanisme impor non-standar mungkin juga tidak disetel.import os
diperlukan untuk ini untuk bekerja. Saya akan menambahkan ini ke dalam jawabannya.import os
danimport os.path
sepenuhnya setara.Ini akan mencetak
foo.py
untukpython foo.py
,dir/foo.py
untukpython dir/foo.py
, dll. Ini adalah argumen pertamapython
. (Perhatikan bahwa setelah py2exe, itu akan menjadifoo.exe
.)sumber
python linkfile.py
, di manalinkfile.py
symlink kerealfile.py
,sys.argv[0]
akan'linkfile.py'
, yang mungkin atau mungkin tidak apa yang Anda inginkan; tentu saja itu yang saya harapkan .__file__
adalah sama: itu akan terjadilinkfile.py
. Jika Anda ingin mencari'realfile.py'
dari'linkfile.py'
, cobaos.path.realpath('linkfile.py')
.__file__
saja.Demi kelengkapan, saya pikir akan bermanfaat untuk merangkum berbagai hasil yang mungkin dan menyediakan referensi untuk perilaku yang tepat dari masing-masing:
__file__
adalah file yang sedang dieksekusi, sebagaimana dirinci dalam dokumentasi resmi :Dari Python3.4 dan seterusnya, per masalah 18416 ,
__file__
selalu merupakan jalur absolut, kecuali jika file yang sedang dieksekusi adalah skrip yang telah dieksekusi secara langsung (bukan melalui penerjemah dengan-m
opsi baris perintah) menggunakan jalur relatif.__main__.__file__
(memerlukan pengimporan__main__
) dengan mudah mengakses__file__
atribut modul utama yang disebutkan di atas , misalnya skrip yang dipanggil dari baris perintah.sys.argv[0]
(wajib mengimporsys
) adalah nama skrip yang dipanggil dari baris perintah, dan mungkin merupakan jalur absolut, sebagaimana dirinci dalam dokumentasi resmi :Seperti disebutkan dalam jawaban lain untuk pertanyaan ini , skrip Python yang dikonversi menjadi program yang dapat dieksekusi yang berdiri sendiri melalui alat-alat seperti py2exe atau PyInstaller mungkin tidak menampilkan hasil yang diinginkan ketika menggunakan pendekatan ini (yaitu
sys.argv[0]
akan menyimpan nama yang dapat dieksekusi daripada nama dari file Python utama dalam executable itu).Jika tidak ada opsi yang disebutkan di atas yang berfungsi, mungkin karena operasi impor yang tidak teratur, modul inspeksi mungkin terbukti bermanfaat. Secara khusus, memohon
inspect.getfile(...)
padainspect.currentframe()
bisa bekerja, meskipun yang terakhir akan kembaliNone
ketika berjalan di sebuah implementasi tanpa Python stack frame.Menangani tautan simbolis
Jika skrip saat ini adalah tautan simbolik, maka semua yang di atas akan mengembalikan jalur tautan simbolik daripada path file asli dan
os.path.realpath(...)
harus dipanggil untuk mengekstrak yang terakhir.Manipulasi lebih lanjut yang mengekstrak nama file yang sebenarnya
os.path.basename(...)
dapat dipanggil pada salah satu di atas untuk mengekstrak nama file yang sebenarnya danos.path.splitext(...)
dapat dipanggil pada nama file yang sebenarnya untuk memotong sufiksnya, seperti padaos.path.splitext(os.path.basename(...))
.Dari Python 3,4 dan seterusnya, per PEP 428 , yang
PurePath
kelas daripathlib
modul dapat digunakan juga pada apapun di atas. Secara khusus,pathlib.PurePath(...).name
mengekstrak nama file aktual danpathlib.PurePath(...).stem
mengekstraksi nama file aktual tanpa akhiran.sumber
Catatan yang
__file__
akan memberikan file tempat kode ini berada, yang dapat diimpor dan berbeda dari file utama yang ditafsirkan. Untuk mendapatkan file utama, modul __main__ khusus dapat digunakan:Catatan yang
__main__.__file__
berfungsi di Python 2.7 tetapi tidak di 3.2, jadi gunakan sintaks import-as seperti di atas untuk membuatnya portabel.sumber
rPython
paket dariR
bahasa. Itu pasti kasus luar biasa yang terlalu sulit untuk ditangani.__main__
internal, untuk digunakan dalam melewati variabel antaraR
danpython
, jadi itu akan relatif mudah untuk membuatnya ditetapkan__main__.__file__
sebelum memanggil yang lain, tapi saya bahkan tidak yakin apa yang akan menjadi nilai yang sesuai dalam kasus ini.Jawaban di atas baik. Tetapi saya menemukan metode ini lebih efisien menggunakan hasil di atas.
Ini menghasilkan nama file skrip aktual bukan jalur.
sumber
Untuk versi Python modern (3.4+),
Path(__file__).name
harus lebih idiomatis. Juga,Path(__file__).stem
memberi Anda nama skrip tanpa.py
ekstensi.sumber
from pathlib import Path
terlebih dahulu.pathlib
diperkenalkan dengan Python 3.4, jadi harusnya mulai dari Python 3.4.Coba ini:
sumber
Catatan: Jika Anda menggunakan Python 3+, Anda harus menggunakan fungsi print ()
Dengan asumsi bahwa nama file adalah
foo.py
, potongan di bawah iniatau
Adapun perluasan lain dengan lebih banyak karakter, misalnya nama file
foo.pypy
Jika Anda ingin mengekstrak dari jalur absolut
akan menampilkan
foo
sumber
__file__
dansys.argv[0]
, lihat stackoverflow.com/questions/5851588/...Argumen pertama dalam sys akan menjadi nama file saat ini sehingga ini akan berfungsi
sumber
Jika Anda melakukan impor yang tidak biasa (mis., Ini adalah file opsi), cobalah:
Perhatikan bahwa ini akan mengembalikan path absolut ke file.
sumber
kita dapat mencoba ini untuk mendapatkan nama skrip saat ini tanpa ekstensi.
sumber
Karena OP meminta nama file skrip saat ini saya lebih suka
sumber
semua jawaban itu bagus, tetapi memiliki beberapa masalah Anda mungkin tidak melihat pada pandangan pertama.
mari tentukan apa yang kita inginkan - kita ingin nama skrip yang dieksekusi, bukan nama modul saat ini - jadi
__file__
hanya akan berfungsi jika digunakan pada skrip yang dieksekusi, bukan dalam modul yang diimpor.sys.argv
juga dipertanyakan - bagaimana jika program Anda dipanggil oleh pytest? atau pydoc runner? atau apakah itu disebut oleh uwsgi?dan - ada metode ketiga untuk mendapatkan nama skrip, saya belum melihat dalam jawaban - Anda dapat memeriksa tumpukan.
Masalah lain adalah, bahwa Anda (atau program lain) dapat mengutak-atik
sys.argv
dan__main__.__file__
- mungkin ada, mungkin tidak. Mungkin valid, atau tidak. Setidaknya Anda dapat memeriksa apakah skrip (hasil yang diinginkan) ada!bitranox perpustakaan saya / lib_programname di github melakukan hal itu:
__main__
ada__main__.__file__
ada__main__.__file__
hasil yang valid (apakah skrip itu ada?)dengan cara itu, solusi saya bekerja sejauh ini dengan
setup.py test
,uwsgi
,pytest
,pycharm pytest
,pycharm docrunner (doctest)
,dreampie
,eclipse
ada juga artikel blog yang bagus tentang masalah itu dari Dough Hellman, "Menentukan Nama Proses dari Python"
sumber
Solusi cepat kotor saya:
sumber
os.path
untuk membagi nama fileos.path.abspath(__file__)
akan memberi Anda jalur absolut (relpath()
tersedia juga).sys.argv[-1]
akan memberi Anda jalan relatif.sumber
Pada Python 3.5, Anda cukup melakukan:
Lihat lebih lanjut di sini: https://docs.python.org/3.5/library/pathlib.html#pathlib.PurePath.stem
Sebagai contoh, saya memiliki file di bawah direktori pengguna saya bernama
test.py
dengan ini di dalam:menjalankan output ini:
sumber