Coleção local de pacotes Python: melhor maneira de importá-los?
Eu preciso enviar umcoleção de programas em Python que usam múltiplospacotes armazenado em um localLibrary
diretório: o objetivo é evitar que os usuários instalem pacotes antes de usar meus programas (os pacotes são enviadosLibrary
diretório). Qual é a melhor maneira de importar os pacotes contidos emLibrary
?
Eu tentei três métodos, mas nenhum deles parece perfeito: existe um método mais simples e robusto? ou é um desses métodos que o melhor pode fazer?
No primeiro método, oLibrary
pasta é simplesmente adicionada ao caminho da biblioteca:
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'Library'))
import package_from_Library
oLibrary
A pasta é colocada no início para que os pacotes enviados com meus programas tenham prioridade sobre os mesmos módulos instalados pelo usuário (dessa forma, tenho certeza de que eles têm a versão correta para trabalhar com meus programas). Este método também funciona quando oLibrary
pasta não está no diretório atual, o que é bom. No entanto, esta abordagem tem desvantagens. Todos e cada um dos meus programas adicionam uma cópia do mesmo caminho parasys.path
, que é um desperdício. Além disso, todos os programas devem conter as mesmas três linhas modificadoras de caminho, o que contraria o princípio Não Repita a Si Mesmo.
Uma melhoria em relação aos problemas acima consiste em tentar adicionarLibrary
caminho apenas uma vez, fazendo isso em um módulo importado:
# In module add_Library_path:
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'Library'))
e depois usar, em cada um dos meus programas:
import add_Library_path
import package_from_Library
Desta forma, graças ao mecanismo de cache do CPython, o móduloadd_Library_path
só é executado uma vez, e oLibrary
caminho é adicionado apenas uma vez parasys.path
. No entanto, uma desvantagem dessa abordagem é queimport add_Library_path
tem um efeito colateral invisível, e que a ordem das importações é importante: isso torna o código menos legível e mais frágil. Além disso, isso força minha distribuição de programas a incluiradd_Library_path.py
programa que os usuários não usarão.
Pythonmódulos deLibrary
também pode ser importado, tornando-se um pacote (vazio__init__.py
arquivo armazenado dentro), o que permite fazer:
from Library import module_from_Library
No entanto, isso quebra parapacotes emLibrary
, como eles podem fazer algo parecidofrom xlutils.filter import …
que quebra porquexlutils
não é encontrado emsys.path
. Então, esse método funciona, mas somente quando inclui módulos emLibrary
, não pacotes.
Todos esses métodos têm alguma desvantagem.
Existe uma maneira melhor de enviar programas com uma coleção de pacotes (que eles usam) armazenados em um localLibrary
diretório? ou é um dos métodos acima (método 1?) o melhor que se pode fazer?
PS: No meu caso, todos os pacotes doLibrary
são pacotes Python puros, mas uma solução mais geral que funciona para qualquer sistema operacional é a melhor.
PPS: O objetivo é que o usuário possa usar meus programas sem ter que instalar nada (além de copiar o diretório que eu envio regularmente), como nos exemplos acima.
PPPS: Mais precisamente, o objetivo é ter a flexibilidade deatualizando minha coleção de programas e seus pacotes de terceiros associados deLibrary
fazendo com que meus usuários façam umcópia simples de um diretório contendo meus programas e oLibrary
pasta de pacotes de terceiros "ocultos". (Eu faço atualizações frequentes, então prefiro não forçar os usuários a atualizar sua distribuição Python também.)