Namespaces de pacote Python

Os namespaces são uma ótima ideia – vamos fazer mais disso!
– Tim Peters, PEP20

Todos nós sabemos (ou deveríamos saber) como os namespaces funcionam no Python. Você coloca um módulo em um caminho específico e pode acessá-lo como path.to.my.module(desde que pathesteja visível para Python usando vários métodos). Não é a isso que “namespace” nesta postagem se refere.

Aqui, estou me referindo à separação de vários submódulos em um namespace raiz comum. Isso pode ser incrivelmente útil para módulos díspares, mas de alguma forma relacionados. Digamos que eu tenha a seguinte configuração de diretório em um projeto em que estou trabalhando:

foo/
__init__
.py
bar
/
__init__
.py
baz
/
__init__
.py

Depois de um monte de trabalho, descobri que eu gostaria de provocação bare bazpara fora em seus próprios módulos de base, dando aos usuários a capacidade de depender apenas os módulos que eles se preocupam em vez de ter que navegar toda a pia da cozinha.

Agora, tudo isso pode ser feito facilmente seguindo convenções horríveis, como usar os nomes foo_bar, foo_bazou outro nome mutilado, mas não é o efeito que desejo. Além de ser feio, isso forçaria todos os dependentes da atualização do pacote para o novo estilo a mudar suas importações. Como tal, não é uma opção viável.

Obviamente, não podemos simplesmente nomear um pacote com a estrutura de diretório interno e ter outro pacote com a estrutura de diretório interno . Certamente, isso introduzirá uma colisão de importação.foo.barfoo/bar/foo.bazfoo/baz

Ou vai?

É aí que namespace_packages(das ferramentas de configuração) entra em jogo. Usando este recurso, você pode definir um namespace raiz para cada pacote a ser usado. Com o exemplo acima, se eu simplesmente definir o namespace_packagecomo "foo", cada pacote com a raiz foonão colidirá um com o outro.

Há duas coisas importantes a lembrar ao usar isso:

  • Nada além de init .py e outros diretórios de submódulo podem existir no diretório do namespace
  • O init .py deve conter ( exigido a partir de 0.7). Não deve conter mais nada.__import__('pkg_resources').declare_namespace(__name__)

http://www.python.org/dev/peps/pep-0382/
http://pythonhosted.org/distribute/setuptools.html#namespace-packages