Experiência de “Novos Ganchos de Importação PEP-302” do Python [fechada]

40

Eu sou um dos desenvolvedores do Ruby (CRuby). Estamos trabalhando no lançamento do Ruby 2.0 (planejado para lançar 2012 / fevereiro).

O Python tem "PEP302: Novos Ganchos de Importação" (2003):

This PEP proposes to add a new set of import hooks that offer better customization of the Python import mechanism. Contrary to the current import hook, a new-style hook can be injected into the existing scheme, allowing for a finer grained control of how modules are found and how they are loaded.

Estamos considerando a introdução de um recurso semelhante ao PEP302 no Ruby 2.0 (CRuby 2.0). Eu quero fazer uma proposta que possa convencer o Matz. Atualmente, o CRuby pode carregar scripts apenas de sistemas de arquivos de uma maneira padrão.

Se você tiver alguma experiência ou consideração sobre o PEP 302, por favor, compartilhe.

Exemplo:

  1. É uma ótima especificação. Não há necessidade de alterá-lo.
  2. É quase bom, mas tem esse problema ...
  3. Se eu pudesse voltar a 2003, mudaria a especificação para ...
por Koichi Sasada 26.06.2012 / 07:35
fonte

3 respostas

47

Sou o mantenedor do módulo runpy do Python e um dos mantenedores do atual sistema de importação. Embora o nosso sistema de importação seja impressionantemente flexível, aconselho que não o adote por atacado sem fazer alguns ajustes - devido a preocupações com a compatibilidade retroativa, há muitas coisas que são mais difíceis do que seriam necessárias de outra forma.

Uma coisa que prejudica o PEP 302 no Python é o tempo que levamos para converter o sistema de importação principal para usá-lo. Na maior parte de uma década, qualquer um que fizesse algo complexo com ganchos de importação estava preso implementando duas partes: uma gerenciando carregadores compatíveis com PEP 302 (como importações de zip) e uma segunda manipulando o mecanismo de importação baseado no sistema de arquivos padrão. É somente no próximo 3.3 que o manuseio de carregadores PEP 302 também cuidará do manuseio de módulos importados através do mecanismo padrão de importação do sistema de arquivos. Tente não repetir esse erro se puder evitá-lo.

O PEP 420 (implementado para o Python 3.3) faz algumas adições ao protocolo para permitir que os importadores contribuam com partes dos pacotes de namespaces. Ele também corrige um problema de nomenclatura na definição da API do Finder (efetivamente substituindo o "find_module" com o nome "find_loader" mais preciso). Isso deve ser documentado com mais clareza na especificação de idioma no momento em que o 3.3rc1 ocorrer em algumas semanas.

Outro problema notável é que a abordagem documentada especificamente no PEP 302 tem um estado global de processo excessivo. Não siga-nos nesse caminho - tente encapsular o estado em um modelo de objeto mais coerente, então é um pouco mais fácil importar seletivamente outros módulos (módulos de extensão C são a ruína de tornar qualquer encapsulamento completamente eficaz, mas até mesmo algum nível de encapsulamento pode ser útil).

O PEP 406 (http://www.python.org/dev/peps/pep-0406/) discute uma possível evolução compatível da abordagem do Python com encapsulamento de estado aprimorado. No entanto, se você tiver um modelo de estado encapsulado desde o início, poderá definir suas APIs de acordo e evitar que importadores e carregadores acessem o estado global (em vez disso, passar uma referência para o mecanismo ativo).

Outra peça que faltava no PEP 302 é a capacidade de perguntar a um importador por um iterador sobre os módulos fornecidos por esse importador (isso é necessário para coisas como utilitários de congelamento e utilitários de documentação automática que extraem doctrings). Como é incrivelmente útil, você provavelmente seria melhor padronizá-lo desde o início: link (nós provavelmente vamos finalmente elevar isso para uma API formalmente especificada no Python 3.4)

E meu último comentário é que você deve dar uma olhada na divisão de responsabilidades entre o sistema de importação e os objetos do carregador. Em particular, considere dividir a API "load_module" em etapas "init_module" e "exec_module" separadas. Isso deve permitir que você minimize o grau em que os carregadores precisam interagir diretamente com o estado de importação.

O PEP 302 e o importlib são um ótimo ponto de partida para um sistema de importação mais flexível, mas definitivamente existem erros que cometemos e que vale a pena evitar.

    
por 23.07.2012 / 08:12
fonte
28

Próximo a ncoghlan Sou o outro mantenedor do sistema de importação do Python e o autor de sua implementação atual, o importlib (http://docs.python.org/dev/py3k/library/importlib.html). Tudo com o que o Nick disse concordou, por isso só quero acrescentar mais informações.

Primeiro, não dependa muito do PEP 302 diretamente, mas observe o que o importlib fornece em termos de classes base abstratas, etc. Para compatibilidade com versões anteriores, as coisas tinham que ser compatíveis com o PEP 302, mas tive que adicionar algumas das minhas próprias APIs para finalizar o suporte à verdadeira flexibilidade.

Outro ponto importante é que você está dando aos desenvolvedores duas partes de flexibilidade. Uma delas é a capacidade de armazenar código de uma forma diferente de apenas diretamente no sistema de arquivos como arquivos individuais (eu chamo isso de back-end de armazenamento para importações), e. isso é permitir que o código viva em um arquivo zip, banco de dados sqlite, etc. O outro suporte é permitir o controle de código pré ou pós-processamento de alguma forma, por exemplo, O Quixote (https://www.mems-exchange.org/software/quixote/) e seu uso alternativo de literais de string não atribuídos a uma variável seriam muito mais fáceis de suportar.

Enquanto o último raramente é necessário, o primeiro é onde você precisa se preocupar com o suporte. E é aí que você acaba redefinindo praticamente as APIs de interação do sistema de arquivos. Como algumas pessoas precisam de ativos armazenados como arquivos com seu código, você precisa fornecer uma boa maneira de ler arquivos, descobrir arquivos, etc. Ainda precisamos implementar a parte da API para descobrir quais arquivos de dados estão disponíveis, listando-os, etc. .

Mas você também tem a necessidade de APIs específicas de código. Como Nick mencionou, você acaba precisando de APIs para descobrir quais módulos um pacote contém, etc., que não são específicos de um arquivo. Existe essa estranha dualidade de ter APIs para lidar com módulos nos quais você extraiu o conceito de arquivos, mas acaba precisando fornecer APIs para acessar dados de ativos semelhantes a arquivos. E assim que você tentar implementar um em relação ao outro para evitar duplicação, as águas ficam realmente escuras (isto é, as pessoas acabam dependendo da estruturação esperada do caminho de arquivo, etc. sem prestar atenção ao fato de que o caminho pode não ser um caminho verdadeiro) porque é para um arquivo zip contendo código e não apenas um arquivo). IOW você acabará tendo que implementar duas APIs similares, mas será melhor para ele no longo prazo.

Como o Nick disse, nossa solução é um bom ponto de partida, mas não é como eu faria hoje se estivesse projetando a API do zero.

    
por 23.07.2012 / 16:27
fonte
-1

O PEP 302 permite conectar-se ao mecanismo de importação do Python, o que significa que você pode importar código de outras fontes, como bancos de dados, arquivos zip e assim por diante.

Na implementação de importações do Python, há uma longa história de complexidade que só em breve será simplificada pela introdução de uma implementação de importação do Python.

Eu devo aconselhar a pensar muito sobre os casos de esquina. Então você provavelmente obterá uma implementação útil.

    
por 23.07.2012 / 06:59
fonte