Como corrigir o erro “ImportError: No module named…” no Python?

115

Qual é a maneira correta de corrigir esse erro ImportError?

Tenho a seguinte estrutura de diretório:

/home/bodacydo
/home/bodacydo/work
/home/bodacydo/work/project
/home/bodacydo/work/project/programs
/home/bodacydo/work/project/foo

E eu estou no diretório

/home/bodacydo/work/project

Agora se eu digitar

python ./programs/my_python_program.py

Eu imediatamente recebo

ImportError: No module named foo.tasks

O ./programs/my_python_program.pycontém a seguinte linha:

from foo.tasks import my_function

Não consigo entender por que o python não encontra ./foo/tasks.py- está lá.

Se eu fizer isso a partir do shell Python, funcionará:

python
>>> from foo.tasks import my_function

Só não funciona se eu chamar via python ./programs/my_python_program.pyscript.

bodacydo
fonte

Respostas:

121

Python não adiciona o diretório atual sys.path, mas sim o diretório em que o script está. Adicione /home/bodacydo/work/projecta sys.pathou $PYTHONPATH.

Ignacio Vazquez-Abrams
fonte
9
Então qual é o objetivo de ter init .py na pasta raiz? Parece não ter nenhum propósito se você editar sys.path ou pythonpath.
11
@Editor: __init__.pyapenas indica que o diretório deve ser tratado como um pacote, quando seu pai está dentro sys.pathou é um pacote.
Ignacio Vazquez-Abrams
3
Além disso, verifique as permissões da pasta. Esse foi o problema no meu caso.
SidJ
15
Para adicionar o dir atual ao caminho python, useexport PYTHONPATH=`pwd`
rodorgas
1
O que funcionou para mim foi adicionar a $ PYTHONPATH o diretório pai do projeto, no seu caso será: /home/bodacydo/work... veja esta resposta
maledr53
33

Você tem um arquivo chamado __init__.pyno diretório foo? Do contrário, o python não reconhecerá foo como um pacote python.

Consulte a seção sobre pacotes no tutorial de python para obter mais informações.

Dave Kirby
fonte
Obrigado e sim, eu tinha __init__.py. O problema desta vez era com $PYTHONPATH. A solução de Ignacio funcionou.
bodacydo
1
Os arquivos init .py são necessários para fazer o Python tratar os diretórios como contendo pacotes; isso é feito para evitar que diretórios com um nome comum, como string, ocultem inadvertidamente módulos válidos que ocorrem posteriormente no caminho de pesquisa do módulo. No caso mais simples, init .py pode ser apenas um arquivo vazio
panofish
Obrigado por me salvar algum dia.
cpu_meltdown
9

Aqui está uma solução passo a passo:

  1. Adicionar um script chamado run.pyem /home/bodacydo/work/projecte editá-lo como este:

    import programs.my_python_program
    programs.my_python_program.main()
    

    (substitua main()pelo método equivalente em my_python_program.)

  2. Vamos para /home/bodacydo/work/project
  3. Corre run.py

Explicação: Como python anexa a PYTHONPATH o caminho do script a partir do qual é executado , a execução run.pyirá anexar /home/bodacydo/work/project. E voilà , import foo.tasksserá encontrado.

ciborgue
fonte
8

Solução de exemplo para adicionar a biblioteca ao seu PYTHONPATH.

  1. Adicione a seguinte linha em seu ~ / .bashrc ou apenas execute-a diretamente:

    export PYTHONPATH="$PYTHONPATH:$HOME/.python"
  2. Em seguida, vincule a biblioteca necessária à pasta ~ / .python, por exemplo

    ln -s /home/user/work/project/foo ~/.python/
Kenorb
fonte
6

Uma solução melhor do que definir PYTHONPATHé usarpython -m module.path

Isso será definido corretamente sys.path[0]e é uma maneira mais confiável de executar módulos.

Eu tenho uma rápida redação sobre este problema, como outros respondentes mencionaram, o motivo para isso é python path/to/file.pycolocar path/tono início de PYTHONPATH( sys.path).

Anthony Sottile
fonte
2

Em minha mente, devo considerar que a foopasta é uma biblioteca independente. Talvez eu queira movê-lo para a Lib\site-packagespasta dentro de uma instalação do Python. Talvez eu queira adicionar um foo.ptharquivo lá.

Eu sei que é uma biblioteca, pois ./programs/my_python_program.pycontém a seguinte linha:

from foo.tasks import my_function

Portanto, não importa que ./programsseja uma pasta irmã para ./foo. É o fato de que my_python_program.pyé executado como um script assim:

python ./programs/my_python_program.py

Quamrana
fonte
0

Se você tiver esse problema ao usar uma versão instalada, ao usar setup.py, certifique-se de que seu módulo está incluído dentropackages

setup(name='Your program',
    version='0.7.0',
    description='Your desccription',
    packages=['foo', 'foo.bar'], # add `foo.bar` here
Danon
fonte