Error de PyLint "No se puede importar": ¿cómo configurar PYTHONPATH?

165

Estoy ejecutando PyLint desde dentro de Wing IDE en Windows. Tengo un subdirectorio (paquete) en mi proyecto y dentro del paquete importo un módulo desde el nivel superior, es decir.

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

Dentro two.pytengo import oney esto funciona bien en tiempo de ejecución, porque el directorio de nivel superior (desde el que myapp.pyse ejecuta) está en la ruta de Python. Sin embargo, cuando ejecuto PyLint en two.py me da un error:

F0401: Unable to import 'one'

¿Cómo puedo solucionar esto?

EMP
fuente

Respuestas:

145

Hay dos opciones que conozco.

Uno, cambie la PYTHONPATHvariable de entorno para incluir el directorio sobre su módulo.

Alternativamente, edite ~/.pylintrcpara incluir el directorio sobre su módulo, de esta manera:

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

(O en otra versión de pylint, init-hook requiere que cambie [General] a [MASTER])

Ambas opciones deberían funcionar.

Espero que ayude.

Brian M. Hunt
fuente
8
Este gancho de pylint es actualmente la mejor manera en VScode ya que PYTHONPATH aún no es compatible porque está integrado en el uso de linter.
Danny Staple
2
Tengo el mismo problema al usar MacVim con Syntastic. ¿Cómo puedo configurar el prosector para corregir el error de importación?
Laurent
Publicación de blog relacionada con algunos detalles más.
Christian Long
~/.pylintrctrabajó para mí en OSX, el otro no funcionó
Miquel
No estoy seguro de por qué esta no es la respuesta aceptada; también, vale la pena mencionar para aquellos que tropiezan con esto, que necesita export PYTHONPATH que pylintlo vea (al menos, en bash / zsh)
Marco Massenzio
43

La solución para alterar la ruta init-hookes buena, pero no me gusta el hecho de que tuve que agregar una ruta absoluta allí, como resultado no puedo compartir este archivo pylintrc entre los desarrolladores del proyecto. Esta solución que usa la ruta relativa al archivo pylintrc funciona mejor para mí:

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

Tenga en cuenta que pylint.config.PYLINTRCtambién existe y tiene el mismo valor que find_pylintrc().

alex_koval
fuente
1
Confirmando que esto realmente proporcionó la solución para los errores de pylint E0611 y E0401. Para usuarios de VSCode: es importante que la carpeta abierta sea la "carpeta raíz de python" y que el archivo .pylintrc esté en esa carpeta.
np8
también, asegúrese de que ninguno de los nombres de directorio de su módulo comience con .(punto).
Saw-mon y Natalie
2
si desea agregar una subcarpeta específica (es decir app) que puede usarfrom pylint.config import find_pylintrc; import os, sys; sys.path.append(os.path.join(os.path.dirname(find_pylintrc()), 'app'))
chachan
27

1) sys.path es una lista.

2) El problema es que a veces sys.path no es tu virtualenv.path y quieres usar pylint en tu virtualenv

3) Entonces, como se dijo, use init-hook (preste atención en 'y "el análisis de pylint es estricto)

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

o

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

.. y

pylint --rcfile /path/to/pylintrc /path/to/module.py
macm
fuente
8
Parecía haber solucionado esto instalando pylinten mi virtualenv según este consejo: plaidzooks.tumblr.com/post/36813101879
Matt
3
Esto funciona muy bien, y debería ser la mejor respuesta. Si no tiene un conjunto .pylintrc, asegúrese de hacer un rápido pylint --generate-rcfile > .pylintrcen su carpeta de inicio.
reka18
26

El problema se puede resolver configurando la ruta de pylint en venv: $ cat .vscode / settings.json

{
    "python.pythonPath": "venv/bin/python",
    "python.linting.pylintPath": "venv/bin/pylint"
}
jeanerpp
fuente
2
Para Windows es { "python.pythonPath": "${workspaceFolder}\\.venv\\Scripts\\python.exe" "python.linting.pylintPath": "${workspaceFolder}\\.venv\\Scripts\\pylint.exe" } solo para completar.
Roy2511
La pregunta no pregunte por este editor.
Ivailo Bardarov
VSCode ahora muestra este mensaje: The setting "python.pythonPath" defined in your settings.json is now deprecated. aunque elimine la python.pythonPathlínea, aún parece funcionar.
Jesse Aldridge
23

¿Tiene un __init__.pyarchivo vacío en ambos directorios para que Python sepa que los directorios son módulos?

El esquema básico cuando no está ejecutando desde la carpeta (es decir, tal vez desde pylint, aunque no lo he usado) es:

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

Así es como el intérprete de Python conoce el módulo sin referencia al directorio actual, por lo que si pylint se ejecuta desde su propia ruta absoluta, podrá acceder functions_etc.pycomo topdir.functions_etco topdir.subdir.other_functions, siempre que topdiresté en el PYTHONPATH.

ACTUALIZACIÓN: Si el problema no es el __init__.pyarchivo, tal vez solo intente copiar o mover su módulo c:\Python26\Lib\site-packages; ese es un lugar común para colocar paquetes adicionales, y definitivamente estará en su pythonpath. Si sabe cómo hacer enlaces simbólicos de Windows o su equivalente (¡no lo hago!), Podría hacerlo en su lugar. Aquí hay muchas más opciones : http://docs.python.org/install/index.html , incluida la opción de agregar sys.path con el directorio de nivel de usuario de su código de desarrollo, pero en la práctica generalmente solo enlace simbólicamente mi directorio de desarrollo local para paquetes de sitio: copiarlo tiene el mismo efecto.

desmontado
fuente
1
Sí, tengo __init__.pyen ambos directorios. Creo que el problema es que el directorio superior NO está en PYTHONPATH cuando se ejecuta PyLint y no estoy seguro de cómo solucionarlo.
EMP
El enlace simbólico es una buena idea, pero solo es compatible con Windows Vista en adelante y estoy ejecutando XP. Supongo que podría intentar vincularlo ...
EMP
re hardlinking: No, mejor no lo hagas. He jugado con él y, aunque ciertamente funciona (en cierto modo), no funcionará como esperabas.
shylent
Los enlaces simbólicos no son una buena idea. Esto solo soluciona el problema en su máquina: cuando alguien más revisa el proyecto, se romperá por ellos.
Jonathan Hartley el
12

respuesta general a esta pregunta que encontré en esta página POR FAVOR NO ABIERTA, EL SITIO ESTÁ ERROR

crear .pylintrcy agregar

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

No sé cómo funciona con WingIDE, pero para usar PyLint con Geany, configuro mi comando externo para:

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

donde% f es el nombre del archivo y% d es la ruta. Puede ser útil para alguien :)

Simón
fuente
4

Tuve que actualizar la PYTHONPATHvariable del sistema para agregar mi ruta de App Engine. En mi caso, solo tuve que editar mi ~/.bashrcarchivo y agregar la siguiente línea:

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

De hecho, intenté configurar el init-hookprimero, pero esto no resolvió el problema de manera consistente en mi base de código (no estoy seguro de por qué). Una vez que lo agregué a la ruta del sistema (probablemente una buena idea en general), mis problemas desaparecieron.

Brian Moeskau
fuente
3

Una solución que acabo de descubrir es ejecutar PyLint para todo el paquete, en lugar de un solo archivo. De alguna manera, logra encontrar el módulo importado entonces.

EMP
fuente
Suena genial; ¿cómo?
Cees Timmerman
1
@CeesTimmerman Ejecutar pylint ... dirdesde la carpeta principal. Esto requiere __init__.pyestar presente en cada subcarpeta con .pyarchivos.
yugr
3

Tratar

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

Tenga en cuenta que en Python 3, la sintaxis de la parte en la elsecláusula sería

from .. import one

Pensándolo bien, esto probablemente no solucionará su problema específico. No entendí la pregunta y pensé que two.py se estaba ejecutando como el módulo principal, pero ese no es el caso. Y teniendo en cuenta las diferencias en la forma en que Python 2.6 (sin importar absolute_importdesde __future__) y Python 3.x manejan las importaciones, de todos modos no necesitaría hacer esto para Python 2.6, no creo.

Aún así, si finalmente cambia a Python 3 y planea usar un módulo como módulo de paquete y como un script independiente dentro del paquete, puede ser una buena idea mantener 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

en mente.

EDITAR: Y ahora para una posible solución a su problema real. Ejecute PyLint desde el directorio que contiene su onemódulo (quizás a través de la línea de comando) o coloque el siguiente código en algún lugar cuando ejecute PyLint:

import os

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

Básicamente, como alternativa a jugar con PYTHONPATH, solo asegúrese de que el directorio de trabajo actual sea el directorio que contiene one.py cuando realiza la importación.

(Mirando la respuesta de Brian, probablemente podrías asignarle el código anterior init_hook, pero si vas a hacer eso, entonces simplemente puedes agregar lo sys.pathque él hace, que es un poco más elegante que mi solución).

PINCHAZO
fuente
2

La clave es agregar el directorio de su proyecto sys.pathsin tener en cuenta la variable env.

Para alguien que usa VSCode, aquí hay una solución de una línea para usted si hay un directorio base de su proyecto:

[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)'

Déjame explicarte un poco:

  • re.search(r".+\/" + base_dir, os.getcwd()).group(): encuentra el directorio base de acuerdo con el archivo de edición

  • os.path.join(os.getcwd(), base_dir): agregar cwdpara sys.pathcumplir con el entorno de línea de comandos


FYI, aquí está mi .pylintrc:

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

chuyik
fuente
2

Tuve este mismo problema y lo solucioné instalando pylint en mi virtualenv y luego agregando un archivo .pylintrc a mi directorio de proyecto con lo siguiente en el archivo:

[Master]
init-hook='sys.path = list(); sys.path.append("./Lib/site-packages/")'
Nate
fuente
Tengo que confirmar que esto elimina los errores de pylint E0611, pero los errores E0401 permanecen.
np8
1

¿Tal vez agregando manualmente el directorio dentro de PYTHONPATH?

sys.path.append(dirname)
Mario Mikić
fuente
Hmm, pero ¿dónde pondrías ese código? En la parte superior de todos y cada uno de los archivos? Supongo que funcionaría, pero es un gran truco solo para que PyLint funcione.
EMP
@Evgeny: Vea la respuesta que Brian M. Hunt publicó recientemente.
JAB
Y agregar esto en la parte superior de cada archivo no funciona por alguna razón: PyLint parece perfectamente contento de ignorar cualquier modificación a sys.path realizada desde los módulos que está escaneando. Sin embargo, no me he molestado en investigar por qué ...
javawizard
1

Tuve el mismo problema y, dado que no pude encontrar una respuesta, espero que esto pueda ayudar a cualquier persona con un problema similar.

Yo uso flymake con epylint. Básicamente, lo que hice fue agregar un dired-mode-hook que verifica si el directorio dired es un directorio de paquete de Python. Si es así, lo agrego a PYTHONPATH. En mi caso, considero que un directorio es un paquete de Python si contiene un archivo llamado "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 esto ayude.

usuario2826500
fuente
1

En caso de que alguien esté buscando una manera de ejecutar pylint como herramienta externa en PyCharm y hacer que funcione con sus entornos virtuales (por qué llegué a esta pregunta), así es como lo resolví:

  1. En PyCharm> Preferencias> Herramientas> Herramientas externas, agregue o edite un elemento para pylint.
  2. En la Configuración de la herramienta del cuadro de diálogo Editar herramienta, configure el Programa para usar pylint desde el directorio de intérpretes de python: $PyInterpreterDirectory$/pylint
  3. Establezca sus otros parámetros en el campo Parámetros, como: --rcfile=$ProjectFileDir$/pylintrc -r n $FileDir$
  4. Establezca su directorio de trabajo en $FileDir$

Ahora, usar pylint como herramienta externa ejecutará pylint en cualquier directorio que haya seleccionado usando un archivo de configuración común y usará cualquier intérprete configurado para su proyecto (que presumiblemente es su intérprete virtualenv).

tterry
fuente
1

Esta es una pregunta antigua pero no tiene respuesta aceptada, por lo que sugeriré esto: cambie la declaración de importación en two.py para leer:

from .. import one

En mi entorno actual (Python 3.6, VSCode usando pylint 2.3.1) esto borra la declaración marcada.

Mike C
fuente
1

Encontré una buena respuesta . Edite su pylintrc y agregue lo siguiente en 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
fuente
1

Cuando instala Python, puede configurar la ruta. Si la ruta ya está definida, entonces lo que puede hacer es dentro del Código VS, presione Ctrl + Shift + P y escriba Python: Seleccione Intérprete y seleccione la versión actualizada de Python. Siga este enlace para obtener más información, https://code.visualstudio.com/docs/python/environments

Nadeem
fuente
0

si usa vscode, asegúrese de que el directorio de su paquete esté fuera del directorio _pychache__.

Vikas Bhutani
fuente
También con el código VS, parece haber problemas potenciales con los puntos en los nombres de las carpetas: github.com/PyCQA/pylint/issues/2182
Eric Burel
0

Si está utilizando Cython en Linux, resolví eliminar module.cpython-XXm-X-linux-gnu.soarchivos en el directorio de destino de mi proyecto.

M. Andrade
fuente
0

simplemente agregue este código en el archivo .vscode / settings.json

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

Esto notificará la ubicación de pylint (que es un verificador de errores para python)

usuario3395246
fuente
-1

Hola, pude importar los paquetes desde un directorio diferente. Acabo de hacer lo siguiente: Nota: estoy usando VScode

Pasos para crear un paquete de Python Trabajar con paquetes de Python es realmente simple. Todo lo que necesitas hacer es:

Crea un directorio y dale el nombre de tu paquete. Pon tus clases en ello. Cree un archivo init .py en el directorio

Por ejemplo: tiene una carpeta llamada Framework donde guarda todas las clases personalizadas allí y su trabajo es simplemente crear un archivo init .py dentro de la carpeta llamada Framework.

Y mientras importa, debe importar de esta manera --->

de la base de importación de Framework

así que el error E0401 desaparece. Framework es la carpeta donde acaba de crear init .py y la base es su módulo personalizado que debe importar y trabajar en Hope. ¡¡¡Ayuda !!!

SUNEEL KAUSHIK S
fuente