Saya ingin melihat apa cara terbaik untuk menentukan direktori skrip saat ini di python?
Saya menemukan bahwa, karena banyak cara memanggil kode python, sulit untuk menemukan solusi yang baik.
Berikut ini beberapa masalah:
__file__
tidak ditentukan jika skrip dieksekusi denganexec
,execfile
__module__
didefinisikan hanya dalam modul
Gunakan kasing:
./myfile.py
python myfile.py
./somedir/myfile.py
python somedir/myfile.py
execfile('myfile.py')
(dari skrip lain, yang dapat ditemukan di direktori lain dan yang dapat memiliki direktori saat ini.
Saya tahu bahwa tidak ada solusi yang sempurna, tetapi saya sedang mencari pendekatan terbaik yang memecahkan sebagian besar kasus.
Pendekatan yang paling banyak digunakan adalah os.path.dirname(os.path.abspath(__file__))
tetapi ini benar-benar tidak berhasil jika Anda menjalankan skrip dari yang lain dengan exec()
.
Peringatan
Solusi apa pun yang menggunakan direktori saat ini akan gagal, ini bisa berbeda berdasarkan pada cara skrip dipanggil atau dapat diubah di dalam skrip yang sedang berjalan.
python
pythonpath
dirname
bogdan
sumber
sumber
pathlib
solusi Ron Kalian jika Anda menggunakan python 3.4 atau lebih tinggi: stackoverflow.com/a/48931294/1011724python myfile.py
dari shell, ia bekerja, tetapi keduanya:!python %
dan:!python myfile.py
dari dalam vim gagal dengan Sistem tidak dapat menemukan jalur yang ditentukan. Ini sangat menjengkelkan. Adakah yang bisa berkomentar tentang alasan di balik ini dan solusi potensial?Jawaban:
memang yang terbaik yang akan Anda dapatkan.
Tidak biasa mengeksekusi skrip dengan
exec
/execfile
; biasanya Anda harus menggunakan infrastruktur modul untuk memuat skrip. Jika Anda harus menggunakan metode ini, saya sarankan pengaturan__file__
diglobals
Anda meneruskan ke skrip sehingga dapat membaca nama file itu.Tidak ada cara lain untuk mendapatkan nama file dalam kode sebelumnya: seperti yang Anda perhatikan, CWD mungkin berada di tempat yang sama sekali berbeda.
sumber
Jika Anda benar-benar ingin membahas kasus dimana sebuah skrip dipanggil
execfile(...)
, Anda dapat menggunakaninspect
modul untuk menyimpulkan nama file (termasuk path). Sejauh yang saya ketahui, ini akan berfungsi untuk semua kasus yang Anda daftarkan:sumber
chdir()
sebelum fungsi, itu akan mengubah hasilnya. Juga memanggil skrip python dari direktori lain akan mengubah hasilnya, jadi itu bukan solusi yang baik.os.path.expanduser("~")
adalah cara lintas platform untuk mendapatkan direktori pengguna. Sayangnya, itu bukan praktik terbaik Windows untuk menempelkan data aplikasi.chdir()
sebelum menjalankan skrip; ini menghasilkan hasil yang benar. Saya sudah mencoba memanggil skrip dari direktori lain dan juga berfungsi. Hasilnya sama denganinspect.getabsfile()
solusi berbasis .Ini bekerja pada CPython, Jython, Pypy. Ini berfungsi jika skrip dieksekusi menggunakan
execfile()
(sys.argv[0]
dan__file__
solusi berbasis akan gagal di sini). Ini berfungsi jika skrip berada di dalam file zip yang dapat dieksekusi (/ telur) . Ini berfungsi jika skrip "diimpor" (PYTHONPATH=/path/to/library.zip python -mscript_to_run
) dari file zip; mengembalikan jalur arsip dalam kasus ini. Ini berfungsi jika skrip dikompilasi menjadi executable mandiri (sys.frozen
). Ini berfungsi untuk symlink (realpath
menghilangkan tautan simbolik). Ia bekerja dalam interpreter interaktif; mengembalikan direktori kerja saat ini dalam kasus ini.sumber
getabsfile(..)
tidak disebutkan dalam dokumentasi untukinspect
? Itu muncul di sumber yang ditautkan dari halaman itu.getsourcefile()
,getfile()
yang didokumentasikan.Dalam Python 3.4+ Anda dapat menggunakan
pathlib
modul yang lebih sederhana :sumber
Path(__file__)
(tidak perluinspect
modul).Path(__file__)
berikan/path/to/script/currentscript.py
ketika OP ingin mendapatkan/path/to/script/
parent = Path(__file__).resolve().parent
itu. Jauh lebih baik..joinpath()
(atau/
operator) untuk ini, bukan+
.The
os.path...
pendekatan adalah 'hal yang dilakukan' dengan Python 2.Di Python 3, Anda dapat menemukan direktori skrip sebagai berikut:
sumber
Path(__file__).parent
. Tapicwd
itu keliru, itu bukan direktori kerja saat ini , tetapi direktori file . Mereka mungkin sama, tetapi biasanya tidak demikian.Cukup gunakan
os.path.dirname(os.path.abspath(__file__))
dan periksa dengan sangat hati-hati apakah ada kebutuhan nyata untuk kasus di manaexec
digunakan. Ini bisa menjadi tanda desain bermasalah jika Anda tidak dapat menggunakan skrip Anda sebagai modul.Ingatlah Zen dari Python # 8 , dan jika Anda yakin ada argumen yang bagus untuk kasus penggunaan di mana harus digunakan
exec
, maka silakan beri tahu kami beberapa detail lebih lanjut tentang latar belakang masalah.sumber
Akan
lakukan apa yang kamu inginkan? Saya tidak yakin apa yang Anda maksud dengan "direktori skrip saat ini". Apa yang diharapkan dari output untuk kasus penggunaan yang Anda berikan?
sumber
exec('myfile.py')
, sama seperti__file__
dansys.argv[0]
.Pertama .. beberapa kasus penggunaan hilang di sini jika kita berbicara tentang cara menyuntikkan kode anonim ..
Tetapi, pertanyaan sebenarnya adalah, apa tujuan Anda - apakah Anda mencoba untuk menegakkan semacam keamanan? Atau apakah Anda hanya tertarik pada apa yang dimuat.
Jika Anda tertarik pada keamanan , nama file yang diimpor melalui exec / execfile tidak penting - Anda harus menggunakan rexec , yang menawarkan hal berikut:
Namun, jika ini lebih merupakan pengejaran akademis .. berikut adalah beberapa pendekatan konyol yang mungkin bisa Anda gali lebih dalam ..
Contoh skrip:
./deep.py
./deeper.py
/tmp/deepest.py
./codespy.py
Keluaran
Tentu saja, ini adalah cara yang intensif sumber daya untuk melakukannya, Anda akan melacak semua kode Anda .. Tidak terlalu efisien. Tapi, saya pikir ini pendekatan baru karena terus bekerja bahkan ketika Anda masuk lebih dalam ke sarang. Anda tidak dapat mengganti 'eval'. Meskipun Anda bisa menimpa execfile ().
Catatan, pendekatan ini hanya mencakup exec / execfile, bukan 'impor'. Untuk pemuatan kait 'modul' tingkat tinggi, Anda mungkin dapat menggunakan sys.path_hooks (Write-up courtesy of PyMOTW).
Itulah semua yang ada di kepala saya.
sumber
Ini adalah solusi parsial, masih lebih baik dari semua yang dipublikasikan sejauh ini.
Sekarang ini berfungsi semua panggilan tetapi jika seseorang menggunakan
chdir()
untuk mengubah direktori saat ini, ini juga akan gagal.Catatan:
sys.argv[0]
tidak akan berfungsi, akan kembali-c
jika Anda menjalankan skrip denganpython -c "execfile('path-tester.py')"
sumber
Ini harus bekerja dalam banyak kasus:
sumber
Semoga ini membantu: - Jika Anda menjalankan skrip / modul dari mana saja Anda akan dapat mengakses
__file__
variabel yang merupakan variabel modul yang mewakili lokasi skrip.Di sisi lain, jika Anda menggunakan juru bahasa Anda tidak memiliki akses ke variabel itu, di mana Anda akan mendapatkan nama
NameError
danos.getcwd()
akan memberi Anda direktori yang salah jika Anda menjalankan file dari tempat lain.Solusi ini akan memberi Anda apa yang Anda cari dalam semua kasus:
Saya belum benar-benar mengujinya tetapi itu menyelesaikan masalah saya.
sumber