Introdução
O Python como as outras maiores linguagens também possui a forma de distribuição de seus programas (.egg), e além desta forma também pode ser distribuído pela rede através de repositórios Python Package Index (PyPI).
Os pacotes para distribuição existem em quase todas as linguagens conhecidas, C++ (.o,.so,.dll), Java (.jar), Delphi(.exe) e outras, com a finalidade de facilitar a distribuição dos aplicativos criados.
Escopo
Será apresentado como criar um pacote padrão, com estrutura e descrição do pacote.
Andamento
Primeiro o programa tem que existir.
Usaremos funções Void para representar o programa.
Programa mypackage-0.0.1:
- Criar estrutura do programa:
$ mkdir -pv programa/mypackage/{foo,bar} mkdir: created directory ‘programa’ mkdir: created directory ‘programa/mypackage’ mkdir: created directory ‘programa/mypackage/foo’ mkdir: created directory ‘programa/mypackage/bar’
A estrutura fica assim:$ tree programa/ programa/ └── mypackage ├── bar └── foo
- Criandar o programa (Void)
Vamos tabalhar dentro do diretório programa/.
$ cd programa
$ $ cat > mypackage/bar/barfunctions.py << eof > def bar1(): > pass > def bar2(): > pass > def bar3(): > pass > eof $ cat > mypackage/foo/foofunctions.py << eof def foo1(): pass def foo2(): pass def foo3(): pass eof
A estrutura atualizada:$ tree mypackage/ mypackage/ ├── bar │ └── barfunctions.py └── foo └── foofunctions.py
-
setup.py
Agora após o programa criado e testado, vem a parte interessante.
Criar o arquivo programa/setup.py com o conteúdo abaixo:
Este arquivo possui configuração para instalação automática do seu programa, que poderá ser utilizando o python, easy_install ou pip.
Das linhas 5 a 11, são variáveis que coloquei para facilitar a edição deste arquivo, que é modelo para qualquer aplicativo Python.
Para utiliza-lo em outro programa basta modificar NAME(5), DESCRIPTION(7), AUTHOR(8), AUTHOR_EMAIL(9), URL(10), e talvés estas LICENSE(11), install_requires(39), classifiers(44)
A estutrutura atualizada fica assim:
$ tree . . ├── mypackage │ ├── bar │ │ └── barfunctions.py │ └── foo │ └── foofunctions.py └── setup.py
-
MANIFEST.in
O arquivo programa/MANIFEST.in indica ao instalador, quais arquivos fazem parte do pacote, e o quê deverá ser usado durante a instalação.$ cat > MANIFEST.in << eof > graft src/ > graft docs/ > recursive-include mypackage * > include *.cfg *.in *.md *.rst *.txt > eof
em recursive-include mypackage *, mypackage é o nome do seu programa, altere quando reutilizar este arquivo.A estutrutura atualizada fica assim:
$ tree . . ├── MANIFEST.in ├── mypackage │ ├── bar │ │ └── barfunctions.py │ └── foo │ └── foofunctions.py └── setup.py
-
__init__.py
Este é o ultimo arquivo obrigatório.
Necessário para funcionamento do pacote de distribuição, e está localizado dentro de cada subdiretório do programa.
Ele indica onde encontrar os métodos do seu programa.
Para encontrar os métodos, ou funções, vamos usar o comando grep. Quem estiver usando Window, faça manualmente.
$ grep -r def mypackage/bar/barfunctions.py:def bar1(): mypackage/bar/barfunctions.py:def bar2(): mypackage/bar/barfunctions.py:def bar3(): mypackage/foo/foofunctions.py:def foo1(): mypackage/foo/foofunctions.py:def foo2(): mypackage/foo/foofunctions.py:def foo3():
Agora usando 'shell script', vamos formatar a exibição para a nossa necessidade.
$ P=mypackage; grep -r def $P|sed "s|$P/|from $P.|; s|/|.|; s|.py:def| import|; s|(.*||" from mypackage.bar.barfunctions import bar1 from mypackage.bar.barfunctions import bar2 from mypackage.bar.barfunctions import bar3 from mypackage.foo.foofunctions import foo1 from mypackage.foo.foofunctions import foo2 from mypackage.foo.foofunctions import foo3
Em posse dos métodos, criamos os arquivos __init__.py
$ cat > mypackage/bar/__init__.py << eof > from mypackage.bar.barfunctions import bar1 > from mypackage.bar.barfunctions import bar2 > from mypackage.bar.barfunctions import bar3 > eof $ cat > mypackage/foo/__init__.py << eof > from mypackage.foo.foofunctions import foo1 > from mypackage.foo.foofunctions import foo2 > from mypackage.foo.foofunctions import foo3 > eof $ cat > mypackage/__init__.py << eof > __version__ = '0.0.1' > eof
A estutrutura atualizada fica assim:
$ tree . ├── MANIFEST.in ├── mypackage │ ├── bar │ │ ├── barfunctions.py │ │ └── __init__.py │ ├── foo │ │ ├── foofunctions.py │ │ └── __init__.py │ └── __init__.py └── setup.py
-
README.rst
O arquivo programa/README.rst, deve conter informações sobre o seu programa.
Neste modelo ele ficará em branco.
$ > README.rst
-
CONTRIBUTORS.rst
O arquivo programa/CONTRIBUTORS.rst, a lista com os dados de contato de todos que contribuem para o desenvolvimento de seu programa.
Neste modelo ele ficará em branco.
$ > CONTRIBUTORS.rst
-
CHANGES.rst
O arquivo programa/CHANGES.rst, o registro de mudanças e atualizações ocorridas durante o desenvolvimento de seu programa.
Neste modelo ele ficará em branco.
$ > CHANGES.rst
A estutrutura final do mypackage-0.0.1:
$ tree . ├── CHANGES.rst ├── CONTRIBUTORS.rst ├── MANIFEST.in ├── mypackage │ ├── bar │ │ ├── barfunctions.py │ │ └── __init__.py │ ├── foo │ │ ├── foofunctions.py │ │ └── __init__.py │ └── __init__.py ├── README.rst └── setup.py
Esta foi a estrutura básica. Agora vamos dar uma incrementada.
Programa mypackage-0.1.0:
A partir do mypackage-0.0.1, vamos fazer algumas modificações.
- mypackage/__init__.py
$ cat > mypackage/__init__.py << eof import os > __version__ = open(os.path.join("mypackage","version.txt")).read().strip() > eof
Isto fará que o '__version__' receba o seu valor do arquivo 'mypackage/version.txt'
- mypackage/version.txt
Este arquivo não exite na versão 0.0.1. Vamos cria-lo com o comando abaixo:
cat > mypackage/version.txt << eof > 0.1.0 > eof
Agora para saber a versão basta acessar o 'mypackage/version.txt', como todo os programas que acessamos os fontes.
E para reutilizar estes códigos, lembrem-se de alterar o arquivo '__init__.py' como o nome do pacote.
A estutrutura final do mypackage-0.1.0:
$ tree . ├── CHANGES.rst ├── CONTRIBUTORS.rst ├── MANIFEST.in ├── mypackage │ ├── bar │ │ ├── barfunctions.py │ │ └── __init__.py │ ├── foo │ │ ├── foofunctions.py │ │ └── __init__.py │ ├── __init__.py │ └── version.txt ├── README.rst └── setup.py
Programa mypackage-1.0.0:
A partir do mypackage-0.1.0, vamos fazer Novas modificaçôes. E diminuir a quantidade de arquivos para alterar durante a criação de um novo pacote.
O arquivo 'mypackage/__init__.py', possui o conteúdo abaixo:
$ cat mypackage/__init__.py import os __version__ = open(os.path.join("mypackage","version.txt")).read().strip()
Altere para:
$ cat mypackage/__init__.py import os __version__ = open(os.path.join(os.path.dirname(__file__), *rnames)).read()
Com esta alteração, o arquivo '__init__.py', não precisará ser modificado para cada empacotamento.
Arquivos para estudo
- 0.0.1 zip:
wget https://gitlab.com/development-incolume/programa/repository/archive.zip?ref=0.0.1 -O mypackage-0.0.1.zip
- 0.0.1 tgz:
wget https://gitlab.com/development-incolume/programa/repository/archive.tar.gz?ref=0.0.1 -O mypackage-0.0.1.tar.gz
- 0.0.1 git:
git clone --depth 1 -b 0.0.1 https://gitlab.com/development-incolume/programa.git
- 0.1.0 zip:
wget https://gitlab.com/development-incolume/programa/repository/archive.zip?ref=0.1.0 -O mypackage-0.1.0.zip
- 0.1.0 tgz:
wget https://gitlab.com/development-incolume/programa/repository/archive.tar.gz?ref=0.1.0 -O mypackage-0.1.0.tar.gz
- 0.1.0 git:
git clone --depth 1 -b 0.1.0 https://gitlab.com/development-incolume/programa.git
- 1.0.0 zip:
wget https://gitlab.com/development-incolume/programa/repository/archive.zip?ref=1.0.0 -O mypackage-1.0.0.zip
- 1.0.0 tgz:
wget https://gitlab.com/development-incolume/programa/repository/archive.tar.gz?ref=1.0.0 -O mypackage-1.0.0.tar.gz
- 1.0.0 git:
git clone --depth 1 -b 1.0.0 https://gitlab.com/development-incolume/programa.git
Comentários