Saya menggunakan setuptools untuk mendistribusikan paket python saya. Sekarang saya perlu mendistribusikan file data tambahan.
Dari apa yang saya kumpulkan dari dokumentasi setuptools, saya perlu memiliki file data saya di dalam direktori paket. Namun, saya lebih suka file data saya di dalam subdirektori di direktori root.
Apa yang ingin saya hindari:
/ #root
|- src/
| |- mypackage/
| | |- data/
| | | |- resource1
| | | |- [...]
| | |- __init__.py
| | |- [...]
|- setup.py
Yang ingin saya miliki:
/ #root
|- data/
| |- resource1
| |- [...]
|- src/
| |- mypackage/
| | |- __init__.py
| | |- [...]
|- setup.py
Saya hanya merasa tidak nyaman memiliki begitu banyak subdirektori, jika tidak penting. Saya gagal menemukan alasan, mengapa saya / memiliki / meletakkan file di dalam direktori paket. Juga merepotkan untuk bekerja dengan begitu banyak subdirektori bersarang IMHO. Atau adakah alasan bagus yang membenarkan pembatasan ini?
python
setuptools
phant0m
sumber
sumber
__init__.py
file, meskipun file itu kosong. Jadi Anda bisa memisahkan direktori data dengan__init__.py
file kosong agar terlihat seperti sebuah paket. Itu seharusnya mencegah grep dari dalam pohon sumber Anda mengambilnya tetapi itu masih akan dikenali sebagai paket oleh python dan alat pembuatannya.Jawaban:
Opsi 1: Instal sebagai paket data
Keuntungan utama menempatkan file data di dalam root paket Python Anda adalah memungkinkan Anda menghindari kekhawatiran tentang di mana file akan tinggal di sistem pengguna, yang mungkin Windows, Mac, Linux, beberapa platform seluler, atau di dalam Egg. Anda selalu dapat menemukan direktori yang
data
berhubungan dengan root paket Python Anda, tidak peduli di mana atau bagaimana itu diinstal.Misalnya, jika saya memiliki tata letak proyek seperti ini:
Anda dapat menambahkan fungsi
__init__.py
untuk menemukan jalur absolut ke file data:import os _ROOT = os.path.abspath(os.path.dirname(__file__)) def get_data(path): return os.path.join(_ROOT, 'data', path) print get_data('resource1/foo.txt')
Keluaran:
Setelah proyek diinstal sebagai Egg, jalur ke
data
akan berubah, tetapi kodenya tidak perlu diubah:/Users/pat/virtenv/foo/lib/python2.6/site-packages/foo-0.0.0-py2.6.egg/foo/data/resource1/foo.txt
Opsi 2: Instal ke lokasi tetap
Alternatifnya adalah menempatkan data Anda di luar paket Python dan kemudian:
data
diteruskan melalui file konfigurasi, argumen baris perintah atauIni jauh lebih tidak diinginkan jika Anda berencana untuk mendistribusikan proyek Anda. Jika Anda benar - benar ingin melakukan ini, Anda dapat menginstal di
data
mana pun Anda suka pada sistem target dengan menentukan tujuan setiap grup file dengan memasukkan daftar tupel:from setuptools import setup setup( ... data_files=[ ('/var/data1', ['data/foo.txt']), ('/var/data2', ['data/bar.txt']) ] )
Diperbarui : Contoh fungsi shell untuk grep file Python secara rekursif:
atlas% function grep_py { find . -name '*.py' -exec grep -Hn $* {} \; } atlas% grep_py ": \[" ./setup.py:9: package_data={'foo': ['data/resource1/foo.txt']}
sumber
data_files
. Juga, Anda bisa membuat alias shell untuk grep untuk mengabaikan file non-Python, sepertigrep_py
.Saya rasa saya menemukan kompromi yang baik yang akan memungkinkan Anda untuk mempertahankan struktur berikut:
/ #root |- data/ | |- resource1 | |- [...] |- src/ | |- mypackage/ | | |- __init__.py | | |- [...] |- setup.py
Anda harus menginstal data sebagai package_data, untuk menghindari masalah yang dijelaskan dalam contoh jawaban, tetapi untuk menjaga struktur file Anda harus menambahkan setup.py Anda:
try: os.symlink('../../data', 'src/mypackage/data') setup( ... package_data = {'mypackage': ['data/*']} ... ) finally: os.unlink('src/mypackage/data')
Dengan cara ini kita membuat struktur yang sesuai "tepat pada waktunya", dan menjaga susunan pohon sumber kita.
Untuk mengakses file data tersebut dalam kode Anda, Anda 'cukup' menggunakan:
data = resource_filename(Requirement.parse("main_package"), 'mypackage/data')
Saya masih tidak suka harus menentukan 'mypackage' dalam kode, karena data tidak ada hubungannya dengan modul ini, tapi saya rasa ini adalah kompromi yang baik.
sumber
Saya pikir pada dasarnya Anda dapat memberikan apa pun sebagai argumen * data_files * untuk setup () .
sumber