Saya menulis paket python dengan modul yang perlu membuka file data dalam ./data/
subdirektori. Saat ini saya memiliki path ke file yang di-hardcode ke dalam kelas dan fungsi saya. Saya ingin menulis kode yang lebih kuat yang dapat mengakses subdirektori di mana pun itu diinstal pada sistem pengguna.
Saya sudah mencoba berbagai metode, tetapi sejauh ini saya tidak beruntung. Tampaknya sebagian besar perintah "direktori saat ini" mengembalikan direktori interpreter python sistem, dan bukan direktori modul.
Sepertinya ini sepele, masalah umum. Namun sepertinya saya tidak bisa memahaminya. Sebagian masalahnya adalah file data saya bukan .py
file, jadi saya tidak bisa menggunakan fungsi impor dan sejenisnya.
Ada saran?
Sekarang direktori paket saya terlihat seperti:
/
__init__.py
module1.py
module2.py
data/
data.txt
Saya mencoba mengakses data.txt
dari module*.py
!
Jawaban:
Anda dapat menggunakan
__file__
untuk mendapatkan path ke paket, seperti ini:sumber
__file__
tidak berfungsi dengan py2exe, karena nilainya akan menjadi path ke file zip.Cara standar untuk melakukan ini adalah dengan paket setuptools dan pkg_resources.
Anda dapat mengatur paket Anda sesuai dengan hierarki berikut, dan mengonfigurasi file pengaturan paket untuk mengarahkannya ke sumber daya data Anda, sesuai tautan ini:
http://docs.python.org/distutils/setupscript.html#installing-package-data
Anda kemudian dapat menemukan kembali dan menggunakan file-file itu menggunakan pkg_resources, sesuai tautan ini:
http://peak.telecommunity.com/DevCenter/PkgResources#basic-resource-access
sumber
python-setuptools
hanya bergantung pada itu? Sejauh ini__file__
berfungsi dengan baik untuk saya.from pkg_resources import resource_filename open(resource_filename('data', 'data.txt'), 'rb')
importlib.resources
gantipkg_resources
untuk tujuan ini (karena masalah kinerja).Untuk memberikan solusi yang berfungsi hari ini. Jelas menggunakan API ini untuk tidak menemukan kembali semua roda itu.
Nama file sistem file yang benar diperlukan. Telur zip akan diekstraksi ke direktori cache:
Mengembalikan objek seperti file yang dapat dibaca untuk sumber daya yang ditentukan; mungkin berupa file aktual, sebuah StringIO, atau beberapa objek serupa. Aliran berada dalam "mode biner", dalam arti bahwa byte apa pun dalam sumber daya akan dibaca apa adanya.
Paket Discovery dan Akses Sumberdaya menggunakan pkg_resources
sumber
Seringkali tidak ada gunanya membuat jawaban yang merinci kode yang tidak berfungsi sebagaimana mestinya, tapi saya percaya ini sebagai pengecualian. Python 3.7 menambahkan
importlib.resources
yang seharusnya digantipkg_resources
. Ini akan berfungsi untuk mengakses file di dalam paket yang tidak memiliki garis miring pada namanya, yaitumisalnya Anda dapat mengakses
data2.txt
paket dalamfoo
dengan misalnyatetapi akan gagal dengan pengecualian untuk
Hal ini tidak bisa diperbaiki kecuali dengan menempatkan
__init__.py
didata
dan kemudian menggunakannya sebagai sebuah paket:Alasan perilaku ini adalah "itu karena desain" ; tetapi desain mungkin berubah ...
sumber
"This was a deliberate choice, but I think you have a valid use case. @brettcannon what do you think? And if we allow this, should we make sure it gets into Python 3.7?"
Anda memerlukan nama untuk seluruh modul Anda, Anda diberikan pohon direktori tidak mencantumkan detail itu, bagi saya ini bekerja:
Terlihat setuptools tampaknya tidak menyelesaikan file berdasarkan nama yang cocok dengan file data yang dikemas, jadi Anda harus memasukkan
data/
awalan cukup banyak tidak peduli apa. Anda dapat menggunakanos.path.join('data', 'data.txt)
jika Anda memerlukan pemisah direktori alternatif, Umumnya saya tidak menemukan masalah kompatibilitas dengan pemisah direktori unix style hard-coded sekalipun.sumber
Saya pikir saya mencari jawaban.
Saya membuat modul data_path.py, yang saya impor ke modul saya yang lain yang berisi:
Dan kemudian saya membuka semua file saya dengan
sumber
pkg_resources.resource_string('pkg_name', 'data/file.txt')
__file__
suatu tempat. Dalam kasus saya, saya menggunakan perpustakaan yang benar-benar menginginkan jalur dan bukan stream. Tentu saja saya bisa menulis file sementara ke disk tetapi malas saya hanya menggunakan fitur setuptools.