Saya biasa membuka file yang berada di direktori yang sama dengan skrip Python yang sedang berjalan dengan hanya menggunakan perintah seperti
open("Some file.txt", "r")
Namun, saya menemukan bahwa ketika skrip dijalankan di Windows dengan mengklik dua kali, skrip akan mencoba membuka file dari direktori yang salah.
Sejak itu saya telah menggunakan perintah form
open(os.path.join(sys.path[0], "Some file.txt"), "r")
setiap kali saya ingin membuka file. Ini berfungsi untuk penggunaan khusus saya, tetapi saya tidak yakin apakah sys.path[0]
mungkin gagal dalam beberapa kasus penggunaan lainnya.
Jadi pertanyaan saya adalah: Apa cara terbaik dan paling dapat diandalkan untuk membuka file yang ada di direktori yang sama dengan skrip Python yang sedang berjalan?
Inilah yang saya sudah bisa mencari tahu sejauh ini:
os.getcwd()
danos.path.abspath('')
kembalikan "direktori kerja saat ini", bukan direktori skrip.os.path.dirname(sys.argv[0])
danos.path.dirname(__file__)
kembalikan jalur yang digunakan untuk memanggil skrip, yang mungkin relatif atau bahkan kosong (jika skrip berada di cwd). Juga,__file__
tidak ada ketika skrip dijalankan di IDLE atau PythonWin.sys.path[0]
danos.path.abspath(os.path.dirname(sys.argv[0]))
sepertinya mengembalikan direktori skrip. Saya tidak yakin apakah ada perbedaan antara keduanya.
Edit:
Saya baru menyadari bahwa apa yang ingin saya lakukan akan lebih baik digambarkan sebagai "buka file di direktori yang sama dengan modul yang mengandung". Dengan kata lain, jika saya mengimpor modul yang saya tulis itu di direktori lain, dan modul itu membuka file, saya ingin mencari file di direktori modul. Saya tidak berpikir apa pun yang saya temukan dapat melakukan itu ...
__file__
tidak dapat digunakan, maka gunakansys.argv[0]
sebagai gantinyadirname(__file__)
. Sisanya harus bekerja seperti yang diharapkan. Saya suka menggunakan__file__
karena dalam kode pustaka,sys.argv[0]
mungkin tidak menunjuk ke kode Anda sama sekali, terutama jika diimpor melalui beberapa skrip pihak ke-3.realpath( join( getcwd(), dirname(__file__) ))
seperti yang dijelaskan di sini?Mengutip dari dokumentasi Python:
sys.path [0] adalah apa yang Anda cari.
sumber
os.path.join(sys.path[0], 'some file.txt')
. Itu harus menangani spasi dan garis miring dengan benar pada semua sistem.Oke, inilah yang saya lakukan
sys.argv selalu apa yang Anda ketikkan ke terminal atau gunakan sebagai path file ketika mengeksekusinya dengan python.exe atau pythonw.exe
Misalnya Anda dapat menjalankan file text.py beberapa cara, mereka masing-masing memberi Anda jawaban berbeda mereka selalu memberi Anda jalan yang diketikkan python.
Ok jadi ketahuilah Anda bisa mendapatkan nama file, masalah besar, sekarang untuk mendapatkan direktori aplikasi Anda bisa tahu menggunakan os.path, khususnya abspath dan dirname
Itu akan menampilkan ini:
itu akan selalu menampilkan ini tidak masalah jika Anda mengetik python test.py atau python "C: \ Documents and Settings \ Admin \ test.py"
Masalah dengan menggunakan __file__ Pertimbangkan dua file ini test.py
import_test.py
Output dari "python test.py"
Output dari "python test_import.py"
Jadi seperti yang Anda lihat file memberi Anda selalu file python itu sedang dijalankan, sedangkan sys.argv [0] memberi Anda file yang selalu Anda jalankan dari interpreter. Tergantung pada kebutuhan Anda, Anda harus memilih mana yang paling sesuai dengan kebutuhan Anda.
sumber
__file__
adalah seharusnya untuk "selalu memberikan jalan untuk file saat ini", dansys.argv[0]
yang seharusnya untuk "selalu memberikan jalan script yang memulai proses". Bagaimanapun, menggunakan__file__
dalam skrip yang dipanggil selalu memberi Anda hasil yang tepat.__file__
di bagian atas skrip, itu akan berfungsi seperti yang diharapkan.Saya dapat menggunakan kode yang disediakan oleh dcolish dengan sukses karena saya mengalami masalah serupa dengan membaca file teks tertentu. File tidak dalam cwd yang sama dengan file Python.
sumber
Saya akan melakukannya dengan cara ini:
Kode di atas membangun path absolut ke file menggunakan abspath dan setara dengan menggunakan
normpath(join(os.getcwd(), path))
[itu dari pydocs]. Kemudian memeriksa apakah file itu benar-benar ada dan kemudian menggunakan manajer konteks untuk membukanya sehingga Anda tidak harus ingat untuk memanggil tutup pada pegangan file. IMHO, melakukannya dengan cara ini akan menghemat banyak rasa sakit dalam jangka panjang.sumber
os.path.abspath
tidak menyelesaikan jalur ke file di folder yang sama dengan skrip jika skrip tidak ada di direktori saat ini.