Python Paketleme
Python paketleme sistemiyle kaynak kodumuzu paketleyerek ona pip
install ya da setup.py install sonrası herhangi bir dış dizin ya da
yeni bilgisayardan import ile erisebilmemiz sağlanır. Paketler
global kurulabilir ama çoğunlukla virtualenv benzeri sanal
geliştirme ortamı içinde kurulurlar.
Kurulum için bir setup.py gerekir. Mesela modul1 adında paylaşmak
istediğimiz bir kod var, kodlar /home/vs/dizin/modul1 altında, bu
dizinde en üst seviyede bir setup.py koyarız,
from setuptools import setup
setup(name='modul1',
version='0.1',
description='Modul 1 cok onemli seyler yapar',
url='https://github.com/user/modul1',
author='Burak Bayramli',
author_email='dd@post.com',
license='MIT',
packages=['modul1'],
install_requires=['dateutil'],
zip_safe=False)
olabilir.
Not: Paketleme servisinin isimleme yöntemi sebebiyle kodlarımızın
modul1 altında bir modul1 alt dizini içinde olması lazım.
Bu altdizin içinde mutlaka bir __init__.py dosyası gerekli, içinde
en basit kullanım için
from .modul1 import *
olmalı. Bu sayede import modul1 deyince __init__.py yükleniyor,
yüklenen bu dosya da diğer kod dosyalarımızı yükleyip kullanıma
açıyor. Böylece mesela modul1/modul1 altında source.py diye bir
dosya varsa, onun içinde de def callme() gibi bir fonksiyon varsa,
üstteki tanım sayesinde modul1.callme() çağrısı artık yapılabilir.
Şimdi en üst dizinde iken python setup.py install ile kurulum
gerçekleştirebiliriz.
install_requires seçeneğine verilen liste install sırasında pip ile
otomatik kurulacak ek programların listesidir. Üstteki örnekte
dateutil adlı dış Python paketi kurulacaktır.
Eğer setup.py develop dersek belli bazı sembolik bağlantılar
sayesinde modul1 geliştirme dizininde yaptığımız değişiklikler direk
kurulu kütüphane üzerinde etki yaratır. Bu geliştirme (develop) için
çok faydalı.
Eğer global ortamdaysak `install`` çağrısı global, sanal ortamda isek sanal ortama kurulum yapar. Sanal ortam hakkındaki virtualenv yaziları [2, 3].
Eğer paket içine veri dosyaları da eklemek istiyorsak, setup.py içinde
include_package_data=True,
package_data={
"": ["*.zip","*.csv"]
},
eki yapabiliriz. Bu durumda modul1/modul1 altındaki tüm belirtilen
sonekli dosyalar toparlanıp pakete dahil edilecektir. setup.py install
sonrası, mesela benim /home/burak/Documents/env3 sanal geliştirme
ortamım için kurulum
/home/burak/Documents/env3/lib/python3.6/site-packages/modul1-0.1--py3.6.egg
dizini altına gitti, oraya baktım, veri dosyaları oraya koyulmuştu.
Tabii dikkat, bir sorun daha var, paketlenen veriye kod nasıl erişecek? Bir çözüm işleyen kod dosyasının adresinin kod içinde,
data_dir = os.path.dirname(__file__)
ile alınması, ve kod içinde tüm veri erişimlerini mesela veri.zip
için data_dir + "/veri.zip" olarak değiştirmek. Ibare __file__ o
anda içinde olunan dosyanın tüm adresidir, onun baz dizinini alıp veri
dosya erişimini ona göre ayarlıyoruz.
PyPi'da Paket Yayinlama, Pip Hazırlığı
Bildiğimiz gibi Python dosyalarının pip komutu ile kurulabilmesini
sağlayan bir altyapı var. Bu yapı
https://pypi.org/
adresinde, kodumuzu herkesin kullanımına açmak için oraya da
gönderebiliriz [1]. Eğer setup.py kurulumu tam yapılmışsa,
python setup.py sdist bdist_wheel
ile PyPi için gerekli dosyaları da üretmek mümkün, bu dosyalar dist
dizini altında konuluyor. Dikkat, önce python setup.py build komutu
işletin, sonra üsttekini, dist altında iki tane dosya lazım, .zip
ve .whl (install işletmeye gerek yok, bu komut bir .egg dosyası
yaratır, PyPi artık bu dosyaları taşımak istemiyor).
Nihai paketin PyPi'a gönderilmesi için PyPi'a üye olunması lazım, ve twine adlı
araç gerekli, onu
pip install twine
ile kurabiliriz. Kurduktan sonra proje en üst dizininde
twine upload dist/*
işletiriz, sorulunca kullanıcı ve şifre girilir, ve kod PyPi sistemine transfer edilir. Artık
https://pypi.org/project/modul1/
adresinde projemizi görebiliriz. 'Release history' seçilince orada şimdiye
kadar yayınladığımız tüm versiyonlar görülür. Bu versiyon numaraları setup.py
içinde tanımladığımız version tanımını baz alıyor tabii. Versiyon konusundan
devam edersek, eğer setup.py içindeki versiyonu değiştirip sistemi derleyip
PyPi'a twine ile tekrar gönderirsek, yeni versiyon 'Release history' altında
gözükecektir, kullanıcılar PyPi sayfasından ya da pip install modul1==[versiyon]
ile o versiyonlardan herhangi birini kurabilirler.
PyPi dokümantasyonu ile kolay entegre için güzel bir numara şu; nasıl olsa
Github için bir README.md yazıyoruz, bir tane daha ayrı dosyayı PyPi için
yaratmaya gerek yok, eğer setup.py içinde
readme=open("README.md").read()
setuptools.setup(
...
long_description=readme,
long_description_content_type="text/markdown",
..
)
tanımlarsak, bu paketi gönderince README.md içinde olan belgeleme direk
PyPİ sayfası olarak gözükecektir.
Not
PyPI'a versiyon arttırıp yeni kodu derleyip göndermeden önce kendi
yerel kurulumuzda lib/python../site-packages gibi bir dizinde
olacak, eski sürümün dizinini kendimiz silersek daha iyi olur.
Kaynaklar
[1] https://realpython.com/pypi-publish-python-package/#preparing-your-package-for-publication
[2] Virtualenv
[3] http://guide.python-distribute.org/creation.html
Yukarı