Empaquetamiento y distribución de código en Python
Autor: | Carlos Jenkins, KuraLabs S.R.L |
---|---|
Email: | carlos.jenkins@kuralabs.io |
Fecha: | 30 de Enero, 2020 |
Ok, hice un código bien chiva.
Cómo hago para que otras personas puedan usarlo?
Respuesta: setup.py y setuptools.
from setuptools import setup setup( name='mypackage', version='1.0.0', author='KuraLabs S.R.L', author_email='info@kuralabs.io', description='Such an awesome package!', long_description='Place here what will be shown in project page!', url='https://github.com/kuralabs/mypackage/', packages=[ 'mypackage', 'mypackage.args', 'mypackage.hello', ], install_requires=[ 'requests', 'colorlog', ], )
Dónde pongo la versión?
4 lugares:
Debe haber un único lugar.
Dónde pongo la versión? En el __init__.py:
__author__ = 'KuraLabs S.R.L' __email__ = 'info@kuralabs.io' __version__ = '1.10.0'
Cómo la cargo?
Parseo?
def find_version(filename): import re content = read(filename) version_match = re.search( r"^__version__ = ['\"]([^'\"]*)['\"]", content, re.M ) if not version_match: raise RuntimeError('Unable to find version string.') return version_match.group(1)
setup( version=find_version('lib/mypackage/__init__.py'), )
Descripción en el setup.py se mostrará en la página del proyecto.
Y mi README?
setup( long_description=read('README.rst'), )
No olvidar poner el README en el MANIFEST.in!
setup( packages=[ 'mypackage', 'mypackage.args', 'mypackage.hello', ], )
Especificar cada uno de los módulos?!!!!!
Setuptools ayuda:
from setuptools import find_packages setup( packages=find_packages('.'), )
Mejor los paquetes en su propio directorio?
from setuptools import find_packages setup( package_dir={'': 'lib'}, packages=find_packages('lib'), )
setup( install_requires=[ 'requests', 'colorlog', ], )
Y mi requirements.txt?
Lo parseo :D
def find_requirements(filename): import string content = read(filename) requirements = [] ignored = [] for line in content.splitlines(): line = line.strip() if line.startswith('#') or not line: continue if line[:1] not in string.ascii_letters: ignored.append(line) continue requirements.append(line) return requirements
Y lo puedo usar así:
setup( install_requires=find_requirements('requirements.txt'), )
No olvidar poner el requirements.txt en el MANIFEST.in!
Dónde los pongo?
lib/ └── mypackage ├── __init__.py ├── args.py └── data └── config.json
Se empaquetan con package_data.
setup( package_data={ 'mypackage': ['data/*'], }, )
Se cargan con pkg_resources.
Dos modos:
Obtener path:
from pathlib import Path from pkg_resources import resource_filename filepath = Path(resource_filename( __package__, 'data/images/myimage.png' ))
Obtener contenido:
from json import loads from pkg_resources import resource_string content = loads(resource_string( __package__, 'data/defaults.json' ).encode('utf-8'))
Usando entrypoints! Así usamos el __main__.py también!
setup( entry_points={ 'console_scripts': [ 'myexec=mypackage.__main__:main' ], }, )
O bien old school:
setup( scripts=['bin/myexec'], )
Más información aquí:
https://python-packaging.readthedocs.io/en/latest/command-line-scripts.html
Respuesta: Wheel y Source.
python3 setup.py bdist_wheel python3 setup.py sdist
Ojo con el MANIFEST.in!!!!
Respuesta: PyPI, o un PyPI propio! Cómo pypiserver.
Servidor PyPI local? Fácil:
docker run -p 8080:8080 -d pypiserver/pypiserver:latest
Cómo lo uso?
pip3 install --index-url http://localhost:8080/simple/ PACKAGE [PACKAGE2...]
Cómo lo configuro global para mi usuario?
pip3 config --user set global.index-url http://localhost:8080/simple/
Lo anterior escribe la configuración en:
~/.config/pip/pip.conf
Listo. Tengo mi paquete, cómo lo subo a PyPI?
Respuesta: Twine.
sudo pip3 install twine
twine upload --username myuser dist/mypackage-x.y.z.tar.gz twine upload --username myuser dist/mypackage-x.y.z-py3-none-any.whl
Si uso un PyPI propio?
nano ~/.pypirc
Escribimos:
[distutils] index-servers = local [local] repository : http://localhost:8080/legacy username : YOUR.EMAIL@EMAIL.COM password : YOUR.MYPYPI.PASSWORD
Subimos a nuestro PyPI propio con:
twine upload -r local dist/mypackage-x.y.z-py3-none-any.whl
Muchas gracias!
https://carlos.jenkins.co.cr/presentations/packaging
Autor: | Carlos Jenkins, KuraLabs S.R.L |
---|---|
Email: | carlos.jenkins@kuralabs.io |
Web: | https://kuralabs.io/ |