Bagaimana saya bisa mendapatkan versi yang didefinisikan setup.py
dari paket saya (untuk --version
, atau tujuan lain)?
python
setuptools
elmarco
sumber
sumber
Jawaban:
Menginterogasi string versi dari distribusi yang sudah diinstal
Untuk mengambil versi dari dalam paket Anda pada saat runtime (apa yang sebenarnya ditanyakan oleh pertanyaan Anda), Anda dapat menggunakan:
Simpan string versi untuk digunakan selama instalasi
Jika Anda ingin melakukan hal sebaliknya (yang tampaknya merupakan jawaban yang oleh penulis lain tampaknya Anda tanyakan), letakkan string versi di file terpisah dan baca isi file itu
setup.py
.Anda bisa membuat version.py dalam paket Anda dengan sebuah
__version__
baris, lalu membacanya dari setup.py menggunakanexecfile('mypackage/version.py')
, sehingga ia menetapkan__version__
di namespace setup.py.Jika Anda menginginkan cara yang lebih sederhana yang akan bekerja dengan semua versi Python dan bahkan bahasa non-Python yang mungkin memerlukan akses ke string versi:
Simpan string versi sebagai satu-satunya konten file teks biasa, beri nama eg
VERSION
, dan baca file itu selamasetup.py
.File yang sama
VERSION
kemudian akan berfungsi sama baiknya di program lain, bahkan yang non-Python, dan Anda hanya perlu mengubah string versi di satu tempat untuk semua program.Peringatan tentang kondisi lomba saat pemasangan
Ngomong-ngomong, JANGAN mengimpor paket Anda dari setup.py Anda seperti yang disarankan dalam jawaban lain di sini: tampaknya akan bekerja untuk Anda (karena Anda sudah memiliki dependensi paket Anda diinstal), tetapi itu akan mendatangkan malapetaka pada pengguna baru paket Anda. , karena mereka tidak akan dapat menginstal paket Anda tanpa menginstal dependensi secara manual terlebih dahulu.
sumber
execfile
berfungsi dengan sangat baik ... tetapi (sayangnya) tidak bekerja dengan Python 3.with open('mypackage/version.py') as f: exec(f.read())
sebagai penggantiexecfile('mypackage/version.py')
. (Dari stackoverflow.com/a/437857/647002 )contoh studi:
mymodule
Bayangkan konfigurasi ini:
Kemudian bayangkan beberapa skenario biasa di mana Anda memiliki dependensi dan
setup.py
terlihat seperti:Dan sebuah contoh
__init__.py
:Dan misalnya
myclasses.py
:masalah # 1: mengimpor
mymodule
selama pengaturanJika
setup.py
impor Andamymodule
maka selama setup Anda kemungkinan besar akan mendapatkanImportError
. Ini adalah kesalahan yang sangat umum ketika paket Anda memiliki dependensi. Jika paket Anda tidak memiliki dependensi lain selain bawaan, Anda mungkin aman; Namun ini bukan praktik yang baik. Alasan untuk itu adalah bahwa itu bukan bukti masa depan; katakan besok kode Anda perlu mengkonsumsi beberapa ketergantungan lainnya.masalah # 2: dimana saya
__version__
?Jika Anda memasukkan hardcode ke
__version__
dalam,setup.py
maka itu mungkin tidak cocok dengan versi yang akan Anda kirimkan dalam modul Anda. Agar konsisten, Anda akan meletakkannya di satu tempat dan membacanya dari tempat yang sama saat Anda membutuhkannya. Menggunakanimport
Anda mungkin mendapatkan masalah # 1.solusi: à la
setuptools
Anda akan menggunakan kombinasi dari
open
,exec
dan memberikan perintah untukexec
menambahkan variabel:Dan dalam
mymodule/version.py
mengekspos versi:Dengan cara ini, versi dikirimkan bersama modul, dan Anda tidak memiliki masalah selama pengaturan mencoba mengimpor modul yang tidak memiliki dependensi (belum diinstal).
sumber
Teknik terbaik adalah mendefinisikan
__version__
kode produk Anda, lalu mengimpornya ke setup.py dari sana. Ini memberi Anda nilai yang dapat Anda baca di modul yang sedang berjalan, dan hanya memiliki satu tempat untuk mendefinisikannya.Nilai-nilai di setup.py tidak diinstal, dan setup.py tidak bertahan setelah instalasi.
Apa yang saya lakukan (misalnya) di coverage.py:
UPDATE (2017): coverage.py tidak lagi mengimpor sendiri untuk mendapatkan versi. Mengimpor kode Anda sendiri dapat membuatnya tidak bisa dihapus, karena kode produk Anda akan mencoba mengimpor dependensi, yang belum diinstal, karena setup.py adalah yang menginstalnya.
sumber
__version__
itu rusak dalam beberapa cara, maka impor Anda juga akan rusak. Python tidak tahu bagaimana hanya menafsirkan pernyataan yang Anda inginkan. @pjeby benar: jika modul Anda perlu mengimpor modul lain, mereka mungkin belum diinstal, dan itu akan kacau. Teknik ini berfungsi jika Anda berhati-hati bahwa impor tidak menyebabkan rantai panjang impor lainnya.pip install <packagename>
, saya mendapatkan error berikut:ImportError: No module named <packagename>
. PERINGATAN pembaca Anda bahwa Anda tidak dapat menjalankan file setup.py seperti ini di lingkungan di mana paket belum diinstal!Pertanyaan Anda agak kabur, tetapi saya pikir apa yang Anda tanyakan adalah bagaimana menentukannya.
Anda perlu mendefinisikan
__version__
seperti:Dan kemudian Anda dapat mengonfirmasi bahwa setup.py tahu tentang versi yang baru saja Anda tentukan:
sumber
Saya tidak senang dengan jawaban ini ... tidak ingin memerlukan setuptools, atau membuat modul terpisah untuk variabel tunggal, jadi saya datang dengan ini.
Karena ketika Anda yakin modul utama dalam gaya pep8 dan akan tetap seperti itu:
Jika Anda ingin ekstra hati-hati dan menggunakan pengurai nyata:
setup.py agak modul sekali pakai jadi tidak masalah jika itu agak jelek.
Pembaruan: cukup lucu Saya sudah pindah dari ini dalam beberapa tahun terakhir dan mulai menggunakan file terpisah dalam paket yang disebut
meta.py
. Saya memasukkan banyak data meta ke sana yang mungkin ingin saya ubah sesering mungkin. Jadi, bukan hanya untuk satu nilai.sumber
ast.get_docstring()
beberapa.split('\n')[0].strip()
dll untuk secara otomatis mengisidescription
dari sumbernya. Satu hal lagi yang perlu disinkronkanBuat file di pohon sumber Anda, misalnya di yourbasedir / yourpackage / _version.py. Biarkan file itu hanya berisi satu baris kode, seperti ini:
__version__ = "1.1.0-r4704"
Kemudian di setup.py Anda, buka file itu dan uraikan nomor versi seperti ini:
Akhirnya, dalam
yourbasedir/yourpackage/__init__.py
impor _versi seperti ini:Contoh kode yang melakukan ini adalah paket "pyutil" yang saya pelihara. (Lihat pencarian PyPI atau google - stackoverflow melarang saya untuk memasukkan hyperlink ke dalamnya dalam jawaban ini.)
@pjeby benar bahwa Anda tidak boleh mengimpor paket Anda dari setup.py sendiri. Itu akan bekerja ketika Anda mengujinya dengan membuat juru bahasa Python baru dan menjalankan setup.py di dalamnya hal pertama:,
python setup.py
tetapi ada beberapa kasus ketika itu tidak akan berfungsi. Itu karenaimport youpackage
tidak berarti membaca direktori kerja saat ini untuk direktori bernama "paket Anda", artinya mencari arussys.modules
untuk kunci "paket Anda" dan kemudian melakukan berbagai hal jika tidak ada di sana. Jadi selalu berfungsi ketika Anda melakukannyapython setup.py
karena Anda memiliki yang baru, kosongsys.modules
, tetapi ini tidak bekerja secara umum.Misalnya, bagaimana jika py2exe mengeksekusi setup.py Anda sebagai bagian dari proses mengemas aplikasi? Saya telah melihat kasus seperti ini di mana py2exe akan memasukkan nomor versi yang salah pada suatu paket karena paket tersebut mendapatkan nomor versinya
import myownthing
di setup.py-nya, tetapi versi berbeda dari paket itu sebelumnya telah diimpor selama menjalankan py2exe. Demikian juga, bagaimana jika setuptools, easy_install, distribusikan, atau distutils2 sedang mencoba membangun paket Anda sebagai bagian dari proses menginstal paket berbeda yang tergantung pada Anda? Lalu apakah paket Anda dapat diimpor pada saat setup.py sedang dievaluasi, atau apakah sudah ada versi paket Anda yang telah diimpor selama masa juru bahasa Python ini, atau apakah mengimpor paket Anda memerlukan paket lain yang harus diinstal terlebih dahulu , atau memiliki efek samping, dapat mengubah hasil. Saya mengalami beberapa kesulitan dalam mencoba menggunakan kembali paket Python yang menyebabkan masalah untuk alat seperti py2exe dan setuptools karena setup.py mereka mengimpor paket itu sendiri untuk menemukan nomor versinya.Omong-omong, teknik ini berfungsi baik dengan alat untuk secara otomatis membuat
yourpackage/_version.py
file untuk Anda, misalnya dengan membaca riwayat kontrol revisi Anda dan menuliskan nomor versi berdasarkan tag terbaru dalam riwayat kontrol revisi. Berikut adalah alat yang melakukan itu untuk darcs: http://tahoe-lafs.org/trac/darcsver/browser/trunk/README.rst dan di sini adalah potongan kode yang melakukan hal yang sama untuk git: http: // github .com / warner / python-ecdsa / blob / 0ed702a9d4057ecf33eea969b8cf280eaccd89a1 / setup.py # L34sumber
Ini juga harus berfungsi, menggunakan ekspresi reguler dan bergantung pada bidang metadata untuk memiliki format seperti ini:
Gunakan yang berikut di awal setup.py Anda:
Setelah itu, Anda dapat menggunakan metadata dalam skrip Anda seperti ini:
sumber
Dengan struktur seperti ini:
di mana version.py berisi:
Anda dapat melakukan ini di setup.py :
Ini tidak akan menimbulkan masalah dengan dependensi apa pun yang Anda miliki di mymodule / __ init__.py
sumber
Untuk menghindari mengimpor file (dan dengan demikian mengeksekusi kodenya) orang dapat menguraikannya dan memulihkan
version
atribut dari pohon sintaks:Kode ini mencoba untuk menemukan
__version__
atauVERSION
penugasan di tingkat atas pengembalian modul adalah nilai string. Sisi kanan bisa berupa string atau tupel.sumber
Ada seribu cara menguliti kucing - inilah milik saya:
sumber
Membersihkan https://stackoverflow.com/a/12413800 dari @ gringo-suave:
sumber
Sekarang ini kotor dan perlu beberapa pemurnian (bahkan mungkin ada panggilan anggota yang tidak ditemukan di pkg_resources yang saya lewatkan), tetapi saya tidak melihat mengapa ini tidak berhasil, atau mengapa tidak ada yang menyarankan untuk berkencan (Googling sekitar memiliki tidak mengaktifkan ini) ... perhatikan bahwa ini adalah Python 2.x, dan akan membutuhkan pkg_resources (sigh):
sumber
Kami ingin menempatkan informasi meta tentang paket kami
pypackagery
di__init__.py
, tapi tidak bisa karena memiliki dependensi pihak ketiga sebagai PJ Eby sudah menunjukkan (lihat jawaban dan peringatan mengenai kondisi lomba).Kami menyelesaikannya dengan membuat modul terpisah
pypackagery_meta.py
yang hanya berisi informasi meta:kemudian mengimpor informasi meta di
packagery/__init__.py
:dan akhirnya menggunakannya di
setup.py
:Anda harus memasukkan
pypackagery_meta
ke dalam paket Anda denganpy_modules
argumen pengaturan. Kalau tidak, Anda tidak dapat mengimpornya saat instalasi karena distribusi paket akan kekurangannya.sumber
Sederhana dan lurus, buat file yang disebut
source/package_name/version.py
dengan konten berikut:Kemudian, pada file
source/package_name/__init__.py
Anda, Anda mengimpor versi untuk digunakan orang lain:Sekarang, Anda bisa memakai ini
setup.py
Diuji ini dengan Python
2.7
,3.3
,3.4
,3.5
,3.6
dan3.7
di Linux, Windows dan Mac OS. Saya menggunakan paket saya yang memiliki Tes Integrasi dan Unit untuk semua platform tesis. Anda dapat melihat hasil dari.travis.yml
dan diappveyor.yml
sini:Versi alternatif menggunakan pengelola konteks:
Anda juga dapat menggunakan
codecs
modul untuk menangani kesalahan unicode baik pada Python2.7
dan3.6
Jika Anda menulis modul Python 100% dalam C / C ++ menggunakan Python C Extensions, Anda dapat melakukan hal yang sama, tetapi menggunakan C / C ++ alih-alih Python.
Pada kasus ini, buat yang berikut ini
setup.py
:Yang membaca versi dari file
version.h
:Tapi, jangan lupa untuk membuat
MANIFEST.in
menyertakanversion.h
file:Dan itu terintegrasi ke dalam aplikasi utama dengan:
Referensi:
sumber
menyebarkan paket ke server dan konvensi penamaan file untuk paket indeks:
contoh untuk konversi versi dinamis pip:
menang:
Mac:
Temukan contoh setup.py memanggil versi pip dinamis yang cocok dari git commit
sumber
Saya menggunakan variabel lingkungan seperti di bawah ini
VERSION = 0.0.0 python setup.py sdist bdist_wheel
Di setup.py
Untuk pemeriksaan konsistensi dengan versi pengepak, saya menggunakan skrip di bawah ini.
sumber