Erro PyLint "Impossível importar" - como configurar o PYTHONPATH?

165

Estou executando o PyLint de dentro do Wing IDE no Windows. Eu tenho um subdiretório (pacote) no meu projeto e dentro do pacote eu importo um módulo do nível superior, ou seja.

__init__.py
myapp.py
one.py
subdir\
    __init__.py
    two.py

Por dentro two.pyeu tenho import onee isso funciona bem em tempo de execução, porque o diretório de nível superior (a partir do qual myapp.pyé executado) está no caminho do Python. No entanto, quando executo o PyLint no two.py, ocorre um erro:

F0401: Unable to import 'one'

Como faço para corrigir isso?

EMP
fonte

Respostas:

144

Existem duas opções que conheço.

Primeiro, altere a PYTHONPATHvariável de ambiente para incluir o diretório acima do seu módulo.

Como alternativa, edite ~/.pylintrcpara incluir o diretório acima do seu módulo, desta forma:

[MASTER]
init-hook='import sys; sys.path.append("/path/to/root")'

(Ou em outra versão do pylint, o gancho de inicialização requer que você altere [Geral] para [MASTER])

Ambas as opções devem funcionar.

Espero que ajude.

Brian M. Hunt
fonte
8
Atualmente, esse gancho de pylint é a melhor maneira no VScode, já que o PYTHONPATH ainda não é suportado, pois é construído no uso do linter.
Danny Staple
2
Eu tenho o mesmo problema usando o MacVim com sintaxe. Como posso configurar o prosector para corrigir o erro de importação?
Laurent
Postagem relacionada no blog com mais alguns detalhes.
Christian Long
~/.pylintrctrabalhou para mim em OSX, o outro não funcionou
Miquel
Não sei por que esta não é a resposta aceita - Também, vale a pena mencionar para aqueles tropeço sobre isso, o que você precisa export PYTHONPATHpara que pylintvai vê-lo (pelo menos, em bash / zsh)
Marco Massenzio
42

A solução para alterar o caminho init-hooké boa, mas eu não gosto do fato de ter que adicionar um caminho absoluto, pois não posso compartilhar esse arquivo pylintrc entre os desenvolvedores do projeto. Esta solução usando o caminho relativo para o arquivo pylintrc funciona melhor para mim:

[MASTER]
init-hook="from pylint.config import find_pylintrc; import os, sys; sys.path.append(os.path.dirname(find_pylintrc()))"

Observe que pylint.config.PYLINTRCtambém existe e tem o mesmo valor que find_pylintrc().

alex_koval
fonte
1
Confirmando que isso realmente forneceu a solução para erros de pylint E0611 e E0401. Para usuários do VSCode: É importante que a pasta aberta seja a "pasta raiz do python" e que o .pylintrc esteja nessa pasta.
Np8 02/11/19
Além disso, verifique se nenhum dos nomes de diretório do módulo começa com .(ponto).
Saw-mon e Natalie,
2
se você quiser adicionar uma subpasta específica (ie app), você pode usarfrom pylint.config import find_pylintrc; import os, sys; sys.path.append(os.path.join(os.path.dirname(find_pylintrc()), 'app'))
chachan 30/10/19
27

1) sys.path é uma lista.

2) Às vezes, o problema é que o sys.path não é o seu virtualenv.path e você deseja usar o pylint no seu virtualenv

3) Assim como dito, use init-hook (preste atenção em 'e "a análise de pylint é estrita)

[Master]
init-hook='sys.path = ["/path/myapps/bin/", "/path/to/myapps/lib/python3.3/site-packages/", ... many paths here])'

ou

[Master]
init-hook='sys.path = list(); sys.path.append("/path/to/foo")'

.. e

pylint --rcfile /path/to/pylintrc /path/to/module.py
macm
fonte
8
Eu parecia ter corrigido isso instalando pylintem meu virtualenv como por este conselho: plaidzooks.tumblr.com/post/36813101879
Matt
3
Isso funciona muito bem e deve ser a resposta principal. Se você não tiver um conjunto .pylintrc, faça um rápido pylint --generate-rcfile > .pylintrcna sua pasta pessoal.
22918 Reka18
26

O problema pode ser resolvido configurando o caminho do pylint em venv: $ cat .vscode / settings.json

{
    "python.pythonPath": "venv/bin/python",
    "python.linting.pylintPath": "venv/bin/pylint"
}
jeanerpp
fonte
2
Para Windows, é { "python.pythonPath": "${workspaceFolder}\\.venv\\Scripts\\python.exe" "python.linting.pylintPath": "${workspaceFolder}\\.venv\\Scripts\\pylint.exe" } apenas uma questão de integridade.
Roy2511
A pergunta não pede para este editor.
Ivailo Bardarov 15/06
O VSCode agora mostra esta mensagem: The setting "python.pythonPath" defined in your settings.json is now deprecated. Se eu excluir a python.pythonPathlinha, ela ainda parece funcionar.
Jesse Aldridge
23

Você tem um __init__.pyarquivo vazio nos dois diretórios para informar ao python que os diretórios são módulos?

O esquema básico quando você não está executando a partir da pasta (ou seja, talvez do pylint, embora eu não tenha usado isso) é:

topdir\
  __init__.py
  functions_etc.py
  subdir\
    __init__.py
    other_functions.py

É assim que o interpretador python conhece o módulo sem referência ao diretório atual; portanto, se o pylint estiver sendo executado a partir de seu próprio caminho absoluto, ele poderá acessar functions_etc.pycomo topdir.functions_etcou topdir.subdir.other_functions, desde que topdiresteja no PYTHONPATH.

ATUALIZAÇÃO: Se o problema não for o __init__.pyarquivo, talvez apenas tente copiar ou mover seu módulo para c:\Python26\Lib\site-packages- esse é um local comum para colocar pacotes adicionais e definitivamente estará no seu pythonpath. Se você sabe como fazer links simbólicos do Windows ou o equivalente (não sei!), Você pode fazer isso. Há muito mais opções aqui: http://docs.python.org/install/index.html , incluindo a opção de anexar sys.path ao diretório de código de desenvolvimento no nível do usuário, mas, na prática, eu normalmente apenas simbolicamente vinculo meu diretório de desenvolvimento local para pacotes de sites - copiá-lo tem o mesmo efeito.

desmontado
fonte
1
Sim, eu tenho __init__.pynos dois diretórios. Eu acho que o problema é que o diretório superior NÃO está no PYTHONPATH quando o PyLint é executado e não tenho certeza de como consertar isso.
EMP
O link simbólico é uma boa idéia, mas é suportado apenas no Windows Vista e estou executando o XP. Suponho que eu poderia tentar vinculá-lo ...
EMP
re:: Não, é melhor você não fazer isso. Eu brinquei com ele e, embora certamente funcione (de certa forma), não funcionará como você espera.
shylent
Links simbólicos não são uma boa ideia. Isso apenas corrige o problema em sua máquina - quando outra pessoa faz check-out do projeto, ele será quebrado por eles.
23818 Jonathan Hartley
12

resposta geral para esta pergunta que encontrei nesta página POR FAVOR, NÃO ABRA, O SITE ESTÁ ERRADO

criar .pylintrce adicionar

[MASTER]
init-hook="from pylint.config import find_pylintrc;
import os, sys; sys.path.append(os.path.dirname(find_pylintrc()))"
x-magix
fonte
5

Não sei como ele funciona com o WingIDE, mas, para usar o PyLint com o Geany, defino meu comando externo para:

PYTHONPATH=${PYTHONPATH}:$(dirname %d) pylint --output-format=parseable --reports=n "%f"

onde% f é o nome do arquivo e% d é o caminho. Pode ser útil para alguém :)

simon
fonte
4

Eu tive que atualizar a PYTHONPATHvariável do sistema para adicionar meu caminho do App Engine. No meu caso, eu apenas tive que editar meu ~/.bashrcarquivo e adicionar a seguinte linha:

export PYTHONPATH=$PYTHONPATH:/path/to/google_appengine_folder

Na verdade, tentei definir o init-hookprimeiro, mas isso não resolveu o problema de maneira consistente em toda a minha base de código (não sei por que). Depois que o adicionei ao caminho do sistema (provavelmente uma boa ideia em geral), meus problemas desapareceram.

Brian Moeskau
fonte
3

Uma solução alternativa que eu acabei de descobrir é realmente executar o PyLint para todo o pacote, em vez de um único arquivo. De alguma forma, ele consegue encontrar o módulo importado.

EMP
fonte
Parece bom; como?
Cees Timmerman
1
@CeesTimmerman Corra pylint ... dirda pasta pai. Isso requer __init__.pya presença em cada subpasta com .pyarquivos.
yugr 25/08/18
3

Experimentar

if __name__ == '__main__':
    from [whatever the name of your package is] import one
else:
    import one

Observe que no Python 3, a sintaxe da parte da elsecláusula seria

from .. import one

Pensando bem, isso provavelmente não resolverá seu problema específico. Entendi mal a pergunta e pensei que o two.py estava sendo executado como o módulo principal, mas esse não é o caso. E considerando as diferenças na maneira como o Python 2.6 (sem importar absolute_importdo __future__) e o Python 3.x manipulam as importações, você não precisaria fazer isso no Python 2.6 de qualquer maneira, não acho.

Ainda assim, se você mudar para o Python 3 e planejar usar um módulo como um módulo de pacote e como um script independente dentro do pacote, pode ser uma boa ideia manter algo como

if __name__ == '__main__':
    from [whatever the name of your package is] import one   # assuming the package is in the current working directory or a subdirectory of PYTHONPATH
else:
    from .. import one

em mente.

EDIT: E agora para uma possível solução para o seu problema real. Execute o PyLint a partir do diretório que contém seu onemódulo (via linha de comando, talvez) ou coloque o seguinte código em algum lugar ao executar o PyLint:

import os

olddir = os.getcwd()
os.chdir([path_of_directory_containing_module_one])
import one
os.chdir(olddir)

Basicamente, como uma alternativa para mexer com PYTHONPATH, verifique se o diretório de trabalho atual é o diretório que contém one.pyquando você faz a importação.

(Olhando para a resposta de Brian, você provavelmente poderia atribuir o código anterior init_hook, mas se você quiser fazer isso, basta fazer o anexo ao sys.pathque ele faz, o que é um pouco mais elegante que a minha solução.)

JAB
fonte
2

A chave é adicionar o diretório do projeto sys.pathsem considerar a variável env.

Para alguém que usa o VSCode, aqui está uma solução de uma linha para você, se houver um diretório base do seu projeto:

[MASTER]
init-hook='base_dir="my_spider"; import sys,os,re; _re=re.search(r".+\/" + base_dir, os.getcwd()); project_dir = _re.group() if _re else os.path.join(os.getcwd(), base_dir); sys.path.append(project_dir)'

Deixe-me explicar um pouco:

  • re.search(r".+\/" + base_dir, os.getcwd()).group(): encontre o diretório base de acordo com o arquivo de edição

  • os.path.join(os.getcwd(), base_dir): adicione cwdpara sys.pathatender ao ambiente da linha de comandos


FYI, aqui está o meu .pylintrc:

https://gist.github.com/chuyik/f0ffc41a6948b6c87c7160151ffe8c2f

chuyik
fonte
2

Eu tive esse mesmo problema e o corrigi instalando o pylint no meu virtualenv e adicionando um arquivo .pylintrc ao diretório do meu projeto, com o seguinte no arquivo:

[Master]
init-hook='sys.path = list(); sys.path.append("./Lib/site-packages/")'
Nate
fonte
Eu tenho que confirmar que isso se livra dos erros de pylint do E0611, mas os erros do E0401 permanecem.
Np8 02/11/19
1

Talvez anexando manualmente o diretório dentro do PYTHONPATH?

sys.path.append(dirname)
Mario Mikić
fonte
Hmm, mas onde você colocaria esse código? No topo de cada arquivo? Suponho que funcionaria, mas é um hack apenas para fazer o PyLint funcionar.
EMP
@ Evgeny: Veja a resposta que Brian M. Hunt postou recentemente.
JAB 17/06
E adicionar isso na parte superior de cada arquivo não funciona por algum motivo - o PyLint parece perfeitamente satisfeito em ignorar quaisquer modificações no sys.path feitas nos módulos que está sendo digitalizado. I não se preocuparam em pesquisar porque, embora ...
javawizard
1

Eu tive o mesmo problema e, como não consegui encontrar uma resposta, espero que isso possa ajudar alguém com um problema semelhante.

Eu uso flymake com epylint. Basicamente, o que fiz foi adicionar um gancho no modo dired que verifique se o diretório dired é um diretório de pacote python. Se for, eu o adiciono ao PYTHONPATH. No meu caso, considero um diretório um pacote python se ele contiver um arquivo chamado "setup.py".

;;;;;;;;;;;;;;;;;
;; PYTHON PATH ;;
;;;;;;;;;;;;;;;;;

(defun python-expand-path ()
  "Append a directory to the PYTHONPATH."
  (interactive
   (let ((string (read-directory-name 
          "Python package directory: " 
          nil 
          'my-history)))
     (setenv "PYTHONPATH" (concat (expand-file-name string)
                  (getenv ":PYTHONPATH"))))))

(defun pythonpath-dired-mode-hook ()
  (let ((setup_py (concat default-directory "setup.py"))
    (directory (expand-file-name default-directory)))
    ;;   (if (file-exists-p setup_py)
    (if (is-python-package-directory directory)
    (let ((pythonpath (concat (getenv "PYTHONPATH") ":" 
                  (expand-file-name directory))))
      (setenv "PYTHONPATH" pythonpath)
      (message (concat "PYTHONPATH=" (getenv "PYTHONPATH")))))))

(defun is-python-package-directory (directory)
  (let ((setup_py (concat directory "setup.py")))
    (file-exists-p setup_py)))

(add-hook 'dired-mode-hook 'pythonpath-dired-mode-hook)

Espero que isto ajude.

user2826500
fonte
1

Caso alguém esteja procurando uma maneira de executar o pylint como uma ferramenta externa no PyCharm e fazê-lo funcionar com seus ambientes virtuais (por que vim a essa pergunta), veja como eu o resolvi:

  1. Em PyCharm> Preferências> Ferramentas> Ferramentas Externas, Adicionar ou Editar um item para o pilone.
  2. Nas Configurações da ferramenta da caixa de diálogo Editar ferramenta, defina Programa para usar o pylint no diretório do interpretador python: $PyInterpreterDirectory$/pylint
  3. Defina seus outros parâmetros no campo Parâmetros, como: --rcfile=$ProjectFileDir$/pylintrc -r n $FileDir$
  4. Defina seu diretório de trabalho como $FileDir$

Agora, usar o pylint como uma ferramenta externa executará o pylint em qualquer diretório que você selecionou, usando um arquivo de configuração comum e usará qualquer intérprete configurado para o seu projeto (que provavelmente é seu intérprete virtualenv).

tterry
fonte
1

Esta é uma pergunta antiga, mas não tem resposta aceita, por isso vou sugerir o seguinte: altere a declaração de importação em two.py para ler:

from .. import one

No meu ambiente atual (Python 3.6, VSCode usando pylint 2.3.1), isso limpa a instrução sinalizada.

Mike C
fonte
1

Encontrei uma boa resposta . Edite seu pylintrc e adicione o seguinte no master

init-hook="import imp, os; from pylint.config import find_pylintrc; imp.load_source('import_hook', os.path.join(os.path.dirname(find_pylintrc()), 'import_hook.py'))"
Devguru
fonte
1

Ao instalar o Python, você pode configurar o caminho. Se o caminho já estiver definido, o que você pode fazer é no VS Code, pressione Ctrl + Shift + P e digite Python: Select Interpreter e selecione a versão atualizada do Python. Siga este link para obter mais informações, https://code.visualstudio.com/docs/python/environments

Nadeem
fonte
0

se você estiver usando vscode, verifique se o diretório do pacote está fora do diretório _pychache__.

Vikas Bhutani
fonte
Também com o código VS, parece haver problemas em potencial nos nomes de pontos nos nomes de pastas: github.com/PyCQA/pylint/issues/2182
Eric Burel
0

Se você estiver usando o Cython no Linux, resolvi remover module.cpython-XXm-X-linux-gnu.soarquivos no diretório de destino do projeto.

M. Andrade
fonte
0

basta adicionar esse código no arquivo .vscode / settings.json

, "python.linting.pylintPath": "venv / bin / pylint"

Isso notificará a localização do pylint (que é um verificador de erros para python)

user3395246
fonte
-1

Olá, eu era capaz de importar os pacotes de diretório diferente. Eu fiz o seguinte: Nota: estou usando o VScode

Etapas para criar um pacote Python Trabalhar com pacotes Python é realmente simples. Tudo que você precisa fazer é:

Crie um diretório e atribua a ele o nome do seu pacote. Coloque suas aulas nele. Crie um arquivo .py init no diretório

Por exemplo: você tem uma pasta chamada Framework, na qual mantém todas as classes personalizadas, e seu trabalho é apenas criar um arquivo .py init dentro da pasta denominada Framework.

E durante a importação, você precisa importar dessa maneira --->

da base de importação do Framework

Portanto, o erro E0401 desaparece. Framework é a pasta onde você acabou de criar init .py e base é o seu módulo personalizado, para o qual você precisa importar e trabalhar. Espero que ajude !!!!

SUNEEL KAUSHIK S
fonte