Estou executando o Python 2.5.
Esta é a minha árvore de pastas:
ptdraft/
nib.py
simulations/
life/
life.py
(Eu também tenho __init__.py
em cada pasta, omitido aqui para facilitar a leitura)
Como importo o nib
módulo de dentro do life
módulo? Espero que seja possível fazer sem mexer com sys.path.
Nota: O módulo principal em execução está na ptdraft
pasta.
__init__.py
. S. Lott: Eu não sei como verificar ...sys.path
ouPYTHONPATH
respostas e check-out excelente resposta de NP8 . Sim, é uma leitura longa. Sim, parece muito trabalho. Mas é a única resposta que realmente resolve o problema de maneira correta e limpa.Respostas:
Parece que o problema não está relacionado ao fato de o módulo estar em um diretório pai ou algo assim.
Você precisa adicionar o diretório que contém
ptdraft
ao PYTHONPATHVocê disse que
import nib
trabalhou com você, o que provavelmente significa que você se adicionouptdraft
(e não o pai) ao PITONONA.fonte
import sys
e depoissys.path.append("..\<parent_folder>")
Você pode usar importações relativas (python> = 2.5):
(O que há de novo no Python 2.5) PEP 328: importações absolutas e relativas
EDIT : adicionado outro ponto '.' subir dois pacotes
fonte
ValueError: Attempted relative import in non-package
__init__.py
arquivo.__init__.py
não é a única coisa que você tem que fazer: stackoverflow.com/questions/11536764/...As importações relativas (como em
from .. import mymodule
) funcionam apenas em um pacote. Para importar 'mymodule' que está no diretório pai do seu módulo atual:editar : o
__file__
atributo nem sempre é fornecido. Em vez de usaros.path.abspath(__file__)
, agora sugeri o uso do módulo inspecionar para recuperar o nome do arquivo (e o caminho) do arquivo atualfonte
sys.path.insert(1, os.path.join(sys.path[0], '..'))
parentdir
, mas em um dos caminhos já especificados emsys.path
, houver outro módulo com o nome 'mymodule'. Inserir oparentdir
como o primeiro elemento dasys.path
lista garante que o móduloparentdir
seja importado.sys.path.insert(1, os.path.realpath(os.path.pardir))
funciona tambémTambém postei uma resposta semelhante à pergunta sobre importações de pacotes de irmãos. Você pode vê-lo aqui .
Solução sem
sys.path
hacksSumário
packaged_stuff
)setup.py
script create onde você usa setuptools.setup () .pip install -e <myproject_folder>
from packaged_stuff.modulename import function_name
Configuração
Eu assumo a mesma estrutura de pastas da pergunta
Eu chamo a
.
pasta raiz e, no meu caso, está localizada emC:\tmp\test_imports
.Passos
1) Adicione um
setup.py
à pasta raizO conteúdo do
setup.py
pode ser simplesmenteBasicamente "qualquer"
setup.py
funcionaria. Este é apenas um exemplo de trabalho mínimo.2) Use um ambiente virtual
Se você estiver familiarizado com ambientes virtuais, ative um e pule para a próxima etapa. O uso de ambientes virtuais não é absolutamente necessário, mas eles realmente o ajudarão a longo prazo (quando você tiver mais de um projeto em andamento ..). As etapas mais básicas são (executadas na pasta raiz)
python -m venv venv
. /venv/bin/activate
(Linux) ou./venv/Scripts/activate
(Win)Para saber mais sobre isso, basta pesquisar no Google "python virtualenv tutorial" ou similar. Você provavelmente nunca precisará de outros comandos além de criar, ativar e desativar.
Depois de criar e ativar um ambiente virtual, seu console deve fornecer o nome do ambiente virtual entre parênteses.
3) pip instala seu projeto em estado editável
Instale seu pacote de nível superior
myproject
usandopip
. O truque é usar a-e
bandeira ao fazer a instalação. Dessa forma, ele é instalado em um estado editável e todas as edições feitas nos arquivos .py serão automaticamente incluídas no pacote instalado.No diretório raiz, execute
pip install -e .
(observe o ponto, significa "diretório atual")Você também pode ver que ele está instalado usando
pip freeze
4) Importe anexando anteriormente
mainfolder
a cada importaçãoNeste exemplo, o
mainfolder
seriaptdraft
. Isso tem a vantagem de não ocorrer colisões de nomes com outros nomes de módulos (da biblioteca padrão do python ou de módulos de terceiros).Exemplo de uso
nib.py
life.py
Executando life.py
fonte
sys.path
e onde o código normalmente seria instalado pelos usuários finais. Isso é melhor do que ossys.path
hacks (e você pode incluir o uso do PYTHONPATH nessa categoria de hacks de caminho) porque significa que o código em desenvolvimento deve se comportar da mesma maneira para você e para outros usuários. Por outro lado, ao usar modificações de caminho, as instruções de importação seriam resolvidas de uma maneira diferente.Você pode usar o caminho dependente do SO no "caminho de pesquisa do módulo", listado em sys.path . Assim, você pode adicionar facilmente o diretório pai como segue
Se você deseja adicionar o diretório pai-pai,
Isso funciona no python 2 e 3.
fonte
Se a adição da pasta do módulo ao PYTHONPATH não funcionou, você pode modificar a lista sys.path no seu programa em que o interpretador Python procura os módulos a serem importados, a documentação do python diz:
Sabendo disso, você pode fazer o seguinte em seu programa:
fonte
/path/to/ptdraft
teria que ser editado. Existem soluções que elaboram o diretório atual do arquivo e o importam da pasta pai dessa maneira também.Não sabe muito sobre o python 2.
No python 3, a pasta pai pode ser adicionada da seguinte maneira:
... e então é possível importar módulos dele
fonte
'..'
leve ao diretório com o módulo em questão.Aqui está uma resposta simples, para que você possa ver como funciona, pequeno e multiplataforma.
Ele usa apenas módulos internos (
os
,sys
einspect
), portanto, deve funcionarem qualquer sistema operacional (SO) porque o Python foi projetado para isso.
Código mais curto para resposta - menos linhas e variáveis
Por menos linhas que isso, substitua a segunda linha por
import os.path as path, sys, inspect
,adicione
inspect.
no início degetsourcefile
(linha 3) e remova a primeira linha.- no entanto, isso importa todo o módulo, portanto, pode precisar de mais tempo, memória e recursos.
O código da minha resposta ( versão mais longa )
Ele usa um exemplo de uma resposta de estouro de pilha. Como obtenho o caminho do
arquivo executado atualmente no Python? para encontrar a fonte (nome do arquivo) do código em execução com uma ferramenta interna.
Meu código adiciona um caminho de arquivo à lista de caminhos
sys.path
do python,porque isso permite que o Python importe módulos dessa pasta.
Depois de importar um módulo no código, é uma boa ideia executar
sys.path.pop(0)
uma nova linhaquando a pasta adicionada tiver um módulo com o mesmo nome que outro módulo importado
posteriormente no programa. Você precisa remover o item da lista adicionado antes da importação, e não outros caminhos.
Se o seu programa não importar outros módulos, é seguro não excluir o caminho do arquivo, porque
após o término de um programa (ou a reinicialização do shell do Python), as edições são feitas para
sys.path
desaparecer.Notas sobre uma variável de nome de arquivo
Minha resposta não usa a
__file__
variável para obter o caminho do arquivo / nome do arquivo em execução, porque os usuários aqui a descrevem como não confiável . Você não deve usá-lo
para importar módulos da pasta pai em programas usados por outras pessoas.
Alguns exemplos em que não funciona (cite esta questão do Stack Overflow):
• não pode ser encontrado em algumas plataformas • às vezes não é o caminho completo do arquivo
fonte
sys.path.pop(0)
imediatamente após importar o módulo desejado. No entanto, as importações subsequentes ainda foram para esse local. Por exemplo, eu tenhoapp/config
,app/tools
eapp/submodule/config
. Desubmodule
, insiroapp/
para importartools
, removoapp/
e tento importarconfig
, mas recebo emapp/config
vez deapp/submodule/config
.tools
importações também estava importandoconfig
do diretório pai. Então, quando mais tarde tenteisys.path.pop(0); import config
entrarsubmodule
, esperando conseguirapp/submodule/config
, estava realmente conseguindoapp/config
. Evidentemente, o Python retorna uma versão em cache de um módulo com o mesmo nome, em vez de realmente verificar osys.path
módulo correspondente a esse nome.sys.path
neste caso, estava sendo alterado corretamente, o Python simplesmente não estava verificando devido ao carregamento do módulo com o mesmo nome.sys.modules
... sys.modules é gravável. A exclusão de uma chave invalidará a entrada de cache do módulo nomeado, fazendo com que o Python pesquise novamente na próxima importação. ... Cuidado, porém, como se você mantiver uma referência ao objeto do módulo, invalide seu cache e depois importe novamente, os dois objetos serão diferentes. Por outro lado,importlib.reload()
vai reutilizar e reinicializar o conteúdo do módulo ...os.path.realpath(getsourcefile(lambda:0) + "/../..")
. O arquivo de origem atual será anexado com dois símbolos de diretório pai. Eu não useios.path.sep
comogetsourcefile
era retorna uma string usando/
mesmo no Windows.realpath
cuidará de remover duas entradas de diretório do caminho completo (neste caso, o nome do arquivo e, em seguida, o diretório atual) que fornece o diretório pai.Aqui está uma solução mais genérica que inclui o diretório pai no sys.path (funciona para mim):
fonte
import os, sys\n sys.path.insert(0,os.path.pardir)
mesma coisa, mas sorther :) (sem avanços de linha nos comentários)os.path.pardir
, não estará obtendo o caminhosys.path.insert()
__file__
variável que pode não ser confiável (nem sempre é o caminho completo do arquivo, não funciona em todos os sistemas operacionais etc.), como os usuários do StackOverflow mencionaram frequentemente. Alterar a resposta para não incluí-la causará menos problemas e será mais compatível. Para mais informações, consulte stackoverflow.com/a/33532002/3787376 .Eu achei a seguinte maneira para importar um pacote do diretório pai do script. No exemplo, eu gostaria de importar funções
env.py
doapp.db
pacote.fonte
sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
sys.path
é geralmente uma má ideia. Você precisa de alguma maneira ( por exemplo ,PYTHONPATH
) para que sua biblioteca seja acessível a outro código (ou então não é realmente uma biblioteca); basta usar isso o tempo todo!As soluções acima mencionadas também são boas. Outra solução para esse problema é
Se você deseja importar algo do diretório de nível superior. Então,
Além disso, se você deseja importar qualquer módulo do diretório pai. Então,
Além disso, se você deseja importar qualquer módulo do diretório pai. Então,
Dessa forma, você pode importar qualquer método específico, se desejar.
fonte
sys.path.append
hacks acima e não consigo importar minha biblioteca dessa maneira. Isto é o que eu tentei primeiro a fazer antes de começar a google :) Ok, foi estaValueError: attempted relative import beyond top-level package
Para mim, o mais curto e meu oneliner favorito para acessar o diretório pai é:
ou:
os.getcwd () retorna o nome do diretório ativo atual, os.path.dirname (directory_name) retorna o nome do diretório para o passado.
Na verdade, na minha opinião, a arquitetura do projeto Python deve ser feita da maneira que nenhum módulo do diretório filho usará nenhum módulo do diretório pai. Se algo assim acontecer, vale a pena repensar sobre a árvore do projeto.
Outra maneira é adicionar o diretório pai à variável de ambiente do sistema PYTHONPATH.
fonte
Em um caderno Jupyter
Desde que você esteja trabalhando em um notebook Jupyter, esta solução curta pode ser útil:
Funciona mesmo sem um
__init__.py
arquivo.Eu testei com o Anaconda3 no Linux e Windows 7.
fonte
%cd -
após a importação, para que o diretório atual do notebook permaneça inalterado.import sys sys.path.append('../')
fonte
Quando não está em um ambiente de pacote com
__init__.py
arquivos, a biblioteca pathlib (incluída em> = Python 3.4) torna muito conciso e intuitivo anexar o caminho do diretório pai ao PYTHONPATH:fonte
mesmo tipo de estilo que a resposta anterior - mas em menos linhas: P
O arquivo retorna o local em que você está trabalhando
fonte
Trabalhar com bibliotecas. Crie uma biblioteca chamada nib, instale-a usando setup.py, deixe-a residir nos pacotes do site e seus problemas serão resolvidos. Você não precisa encher tudo o que faz em um único pacote. Quebrá-lo em pedaços.
fonte
site-packages
sempre que executá-lo em um computador diferente.Em um sistema Linux, você pode criar um link virtual da pasta "life" para o arquivo nib.py. Em seguida, você pode simplesmente importá-lo como:
fonte