Importe o pacote python do diretório local para o interpretador

86

Estou desenvolvendo / testando um pacote em meu diretório local. Quero importá-lo no interpretador (v2.5), mas sys.path não inclui o diretório atual. Agora eu digito sys.path.insert(0,'.'). Existe uma maneira melhor?

Além disso,

from . import mypackage

falha com este erro:

ValueError: Attempted relative import in non-package
projetos têm
fonte
Onde você leu isso "." era um módulo Python?
S.Lott
16
@Lott: É um caminho de importação relativo descrito aqui: docs.python.org/reference/…
projectshave
1
Você pode querer dar uma olhada neste guia definitivo chrisyeh96.github.io/2017/08/08/…
Kevin Zhu

Respostas:

44

Você pode usar importações relativas apenas de um módulo que por sua vez foi importado como parte de um pacote - seu script ou intérprete interativo não foi, então é claro from . import(o que significa "importar do mesmo pacote de onde fui importado") não 't funciona. import mypackagevai ficar bem depois de garantir o diretório pai mypackageé sys.path(como você conseguiu obter o seu diretório atual longe do sys.pathque eu não sei? - você tem algo estranho no site.py, ou ...)

Para colocar seu diretório atual de volta sys.pathlá, não há maneira melhor do que colocá-lo lá.

Alex Martelli
fonte
Python 2.5 para Ubuntu 8.10 não possui o diretório atual (string vazia) em sys.path para o interpretador. Eu não mudei nada, então de alguma forma foi enviado dessa forma. Acabei de instalar o 3.0 e o sys.path TEM '' no sys.path.
projetos têm
@projectshave, OK, sem dúvida o Ubuntu tem seus motivos! Eu não percebi isso no 8.04 (o que usamos atualmente no trabalho), mas talvez eu simplesmente não estivesse prestando atenção suficiente.
Alex Martelli
1
Estou parcialmente errado. Python invocado de um shell tem o diretório atual em sys.path. Python invocado do Emacs não possui o diretório atual. Estranho.
projetos têm
1
Bem, então é o Emacs que tem seus motivos em oposição aos do Ubuntu (como um usuário do vim, eu realmente não sei ;-). Você pode inserir condicionalmente '.' em seu sys.path iff não existe, é claro.
Alex Martelli
@Alex Martelli: Muito obrigado! Estive pesquisando e procurando a solução de por que meu complemento (para Anki) precisava de uma instrução de importação diferente ao ser executado "localmente" como um script. Quando, em vez disso, adicionei um método local_launch () e importei / iniciei a coisa toda de um script fora da pasta do pacote, funcionou perfeitamente!
Jon Coombs
17

Consulte a documentação para sys.path:

http://docs.python.org/library/sys.html#sys.path

Citar:

Se o diretório do script não estiver disponível (por exemplo, se o interpretador for invocado interativamente ou se o script for lido da entrada padrão), o caminho [0] é a string vazia, que direciona o Python para pesquisar módulos no diretório atual primeiro.

Portanto, não há necessidade de mexer com sys.path se você estiver iniciando o interpretador Python a partir do diretório que contém seu módulo.

Além disso, para importar seu pacote, basta fazer:

import mypackage

Como o diretório que contém o pacote já está em sys.path, ele deve funcionar bem.

SpoonMeiser
fonte
1
Ele falhará se um nome de arquivo semelhante existir em outro lugar no env de trabalho.
JAR.JAR.beans
@ JAR.JAR.beans o diretório de trabalho atual deve ser a primeira coisa, sys.pathentão os arquivos devem ser encontrados antes dos arquivos em qualquer outro lugar no ambiente de trabalho.
SpoonMeiser de
3
Bom ponto. Ou seja, se executarmos o arquivo do diretório local. No caso de ser alguma outra pasta, e no caso de ser necessária uma alteração no sys.path - significa sys.path.insert(0, new_path)ao invés de sys.path.append(new_path).
JAR.JAR.beans
14

Se você deseja executar um script python não modificado para importar bibliotecas de um diretório local específico, você pode definir a PYTHONPATHvariável de ambiente - por exemplo, em bash:

export PYTHONPATH=/home/user/my_libs
python myscript.py

Se você deseja apenas importar do diretório de trabalho atual, use a .notação:

export PYTHONPATH=.
python myscript.py
Pierz
fonte
Exportar PYTHONPATH inclui programação fora do python (por exemplo, em bash). Além disso, em docs.python.org/3/using/cmdline.html está claramente afirmado que " o caminho de pesquisa padrão depende da instalação ".
ilias iliadis
13

Mantenha simples:

 try:
     from . import mymodule     # "myapp" case
 except:
     import mymodule            # "__main__" case
Guido U. Draheim
fonte
7
Gosto desta solução, é a mais simples. A única questão restante é por que a regra "apenas uma maneira de fazer isso" foi considerada opcional ao implementar importações ... Sério, existem cerca de 15 maneiras de declarar e organizar os pacotes, todas com desvantagens
Léo Germond
5

Uma maneira simples de fazer isso funcionar é rodar seu script a partir do diretório pai usando o -msinalizador do python , por exemplo python -m packagename.scriptname. Obviamente, nesta situação, você precisa de um __init__.pyarquivo para transformar seu diretório em um pacote.

bradley.ayers
fonte
5

Dentro de um pacote, se houver setup.py , é melhor instalá-lo

pip install -e .
Nagashayan
fonte
3

O uso sys.pathdeve incluir o diretório atual já.

Tentar:

import .

ou:

from . import sth

no entanto, pode não ser uma boa prática, então por que não usar apenas:

import mypackage
Sunqiang
fonte
5
O problema com <import mypackage> é que ele carrega o pacote do env global do python, pode carregar o pacote / arquivo da pasta local, mas também pode carregar algum outro mypackge aleatório que está no env de trabalho.
JAR.JAR.beans
2

Um pouco tarde para a festa, mas isso é o que funcionou para mim:

>>> import sys
>>> sys.path.insert(0, '')

Aparentemente, se houver uma string vazia, Python sabe que ela deve procurar no diretório atual. Eu não tinha a string vazia sys.path, o que causou este erro.

maninthecomputer
fonte
0

Eu costumava pathlibadicionar meu diretório de módulo ao caminho do meu sistema, pois queria evitar a instalação do módulo como um pacote e a resposta do @maninthecomputer não funcionou para mim

import sys
from pathlib import Path

cwd = str(Path(__file__).parent)
sys.path.insert(0, cwd)
from my_module import my_function
rdmolony
fonte