Eu quero herdar de uma classe em um arquivo que se encontra em um diretório acima do atual.
É possível importar relativamente esse arquivo?
fonte
Eu quero herdar de uma classe em um arquivo que se encontra em um diretório acima do atual.
É possível importar relativamente esse arquivo?
from ..subpkg2 import mod
De acordo com os documentos do Python: Quando estiver dentro de uma hierarquia de pacotes, use dois pontos, como diz o documento da instrução de importação :
Ao especificar qual módulo importar, você não precisa especificar o nome absoluto do módulo. Quando um módulo ou pacote está contido em outro pacote, é possível fazer uma importação relativa no mesmo pacote superior sem precisar mencionar o nome do pacote. Usando pontos iniciais no módulo ou pacote
from
especificado, você pode especificar a altura de percorrer a hierarquia atual do pacote sem especificar nomes exatos. Um ponto inicial significa o pacote atual em que o módulo que está fazendo a importação existe. Dois pontos significam um nível de pacote . Três pontos sobem dois níveis, etc. Portanto, se você executar afrom . import mod
partir de um módulo nopkg
pacote, você terminará importandopkg.mod
. Se você executarfrom ..subpkg2 import mod
de dentro,pkg.subpkg1
você importarápkg.subpkg2.mod
. A especificação para importações relativas está contida no PEP 328 .
O PEP 328 trata de importações absolutas / relativas.
fonte
A resposta do @ gimel está correta se você pode garantir a hierarquia de pacotes que ele menciona. Se você não pode - se sua necessidade real é a que você expressou, exclusivamente vinculada a diretórios e sem qualquer relação necessária com o empacotamento -, você precisa trabalhar
__file__
para descobrir o diretório pai (algumasos.path.dirname
chamadas serão necessárias; -), então (se esse diretório não estiver ligadosys.path
) preceder temporariamente inserção disse dir no início desys.path
,__import__
, retire disse dir novamente - o trabalho sujo de fato, mas, "quando você deve, você deve" (e se esforça para Pyhon nunca impeça o programador de fazer o que deve ser feito - assim como o padrão ISO C diz na seção "Spirit of C" em seu prefácio! -).Aqui está um exemplo que pode funcionar para você:
fonte
sys.path
disponibilizar o mesmo módulo com nomes diferentes e todos os erros correspondentes. autopath.py em pypy ou _preamble.py em twisted resolva-o usando um critério de pesquisa que identifica o pacote de nível superior enquanto percorre os diretórios para cima.sys.path.remove(pathYouJustAdded)
após a importação necessária para não manter esse novo caminho.Importe o módulo de um diretório que esteja exatamente um nível acima do diretório atual:
fonte
from .. import module
I got error ValueError: Tentativa de importação relativa no pacote não seguindo a recomendaçãoComo carregar um módulo que é um diretório ativo
prefácio: reescrevi substancialmente uma resposta anterior com a esperança de ajudar as pessoas a entrar no ecossistema do python, e espero dar a todos a melhor mudança de sucesso com o sistema de importação do python.
Isso cobrirá as importações relativas dentro de um pacote , que eu acho que é o caso mais provável da pergunta do OP.
Python é um sistema modular
É por isso que escrevemos
import foo
para carregar um módulo "foo" no namespace raiz, em vez de escrever:Python não está acoplado a um sistema de arquivos
É por isso que podemos incorporar python em ambientes onde não há um sistema de arquivos defacto sem fornecer um sistema virtual, como o Jython.
A dissociação de um sistema de arquivos permite que as importações sejam flexíveis; esse design permite coisas como importações de arquivos compactados / zip, singletons de importação, cache de bytecode, extensões cffi e até carregamento remoto de definição de código.
Portanto, se as importações não estão acopladas a um sistema de arquivos, o que significa "um diretório ativo"? Temos que escolher algumas heurísticas, mas podemos fazer isso, por exemplo, ao trabalhar em um pacote , já foram definidas algumas heurísticas que fazem com que as importações relativas gostem
.foo
e..foo
funcionem dentro do mesmo pacote. Legal!Se você deseja sinceramente associar seus padrões de carregamento de código-fonte a um sistema de arquivos, você pode fazer isso. Você terá que escolher suas próprias heurísticas, e usar algum tipo de importação de máquinas, eu recomendo importlib
O exemplo importlib do Python se parece com isso:
Embalagem
Há um ótimo exemplo de projeto disponível oficialmente aqui: https://github.com/pypa/sampleproject
Um pacote python é uma coleção de informações sobre seu código-fonte, que pode informar outras ferramentas sobre como copiar seu código-fonte em outros computadores e como integrar seu código-fonte no caminho do sistema para que
import foo
funcione em outros computadores (independentemente do intérprete, sistema operacional do host etc.)Estrutura de Diretórios
Vamos ter um nome de pacote
foo
, em algum diretório (de preferência um diretório vazio).Minha preferência é criar
setup.py
como irmãofoo.py
, porque isso simplifica a gravação do arquivo setup.py, no entanto, você pode escrever a configuração para alterar / redirecionar tudo o que o setuptools faz por padrão, se desejar; por exemplo, colocarfoo.py
em um diretório "src /" é um pouco popular, não abordado aqui..
.
"editável"
-e
, mais uma vez, redirecionará o mecanismo de importação para carregar os arquivos de origem nesse diretório, em vez de copiar os arquivos exatos atuais para a biblioteca do ambiente de instalação. Isso também pode causar diferenças de comportamento na máquina de um desenvolvedor, não deixe de testar seu código! Existem outras ferramentas além do pip, no entanto, eu recomendo que o pip seja o introdutório :)Também gosto de criar
foo
um "pacote" (um diretório que contém__init__.py
) em vez de um módulo (um único arquivo ".py"); ambos "pacotes" e "módulos" podem ser carregados no espaço para nome raiz, os módulos permitem espaços para nome aninhados, o que é útil se quisermos importar "um diretório relativo acima"..
Eu também gosto de fazer a
foo/__main__.py
, isso permite que o python execute o pacote como um módulo, por exemplopython3 -m foo
, executefoo/__main__.py
como__main__
..
Permite detalhar isso com mais alguns módulos: Basicamente, você pode ter uma estrutura de diretórios assim:
setup.py
convencionalmente contém informações de metadados sobre o código-fonte, como:foo
, embora seja popular substituir hífens por sublinhadospython ./setup.py test
É muito expansivo, podendo até compilar extensões em tempo real se um módulo de origem estiver sendo instalado em uma máquina de desenvolvimento. Para um exemplo diário, recomendo o setup.py do repositório de amostras PYPA
Se você estiver liberando um artefato de construção, por exemplo, uma cópia do código destinado a executar computadores quase idênticos, um arquivo requirements.txt é uma maneira popular de capturar informações exatas de dependência, em que "install_requires" é uma boa maneira de capturar o mínimo e versões máximas compatíveis. No entanto, como as máquinas de destino são praticamente idênticas, eu recomendo criar um tarball de um prefixo python inteiro. Isso pode ser complicado, muito detalhado para entrar aqui. Confira
pip install
's--target
opção, ou virtualenv aka venv para leads.de volta ao exemplo
como importar um arquivo em um diretório:
Em foo / spam / eggs.py, se quiséssemos código de foo / baz, poderíamos solicitá-lo por seu espaço de nome absoluto:
Se desejássemos reservar a capacidade de mover eggs.py para outro diretório no futuro com alguma outra
baz
implementação relativa , poderíamos usar uma importação relativa como:fonte
Python é um sistema modular
Python não depende de um sistema de arquivos
Para carregar o código python de forma confiável, tenha esse código em um módulo e esse módulo instalado na biblioteca do python.
Os módulos instalados sempre podem ser carregados no namespace de nível superior com
import <name>
Há um ótimo projeto de amostra disponível oficialmente aqui: https://github.com/pypa/sampleproject
Basicamente, você pode ter uma estrutura de diretórios assim:
.
Certifique-se de declarar o seu
setuptools.setup()
emsetup.py
,exemplo oficial: https://github.com/pypa/sampleproject/blob/master/setup.py
No nosso caso, provavelmente queremos exportar
bar.py
efoo/__init__.py
, meu breve exemplo:setup.py
.
Agora podemos instalar nosso módulo na biblioteca python; com o pip, você pode instalar
the_foo_project
na sua biblioteca python no modo de edição, para que possamos trabalhar em tempo real.
Agora, a partir de qualquer contexto python, podemos carregar nossos py_modules e pacotes compartilhados
foo_script.py
fonte
pip install --edit foo
, quase sempre dentro de um virtualenv. Quase nunca escrevo um módulo que não se destina a ser instalado. se eu entendi mal algo que gostaria de saber.editable
links de ovo e módulos python instalados não são exatamente iguais em todos os aspectos; por exemplo, adicionar um novo espaço para nome a um módulo editável será encontrado na pesquisa de caminho, mas se isso não for exportado no arquivo setup.py, ele não será empacotado / instalado! Teste seu caso de uso :)