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?

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.


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


~/.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().


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

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"
}

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.


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


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 :)


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.


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.


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).


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


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/")'

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)

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.


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).


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.


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

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



0

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


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)


-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 !!!

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.