unable - visual code python linter
Error "Imposible importar" de PyLint: cómo configurar PYTHONPATH? (13)
¿Tal vez agregando manualmente el directorio dentro de PYTHONPATH?
sys.path.append(dirname)
Estoy ejecutando PyLint desde el interior de Wing IDE en Windows. Tengo un subdirectorio (paquete) en mi proyecto y dentro del paquete importo un módulo del nivel superior, es decir.
__init__.py
myapp.py
one.py
subdir/
__init__.py
two.py
Dentro de two.py
he import one
y esto funciona bien en tiempo de ejecución, porque el directorio de nivel superior (desde el cual se ejecuta myapp.py
) está en la ruta de acceso de Python. Sin embargo, cuando ejecuto PyLint en two.py me da un error:
F0401: Unable to import ''one''
¿Cómo puedo solucionar esto?
¿Tiene un archivo __init__.py
vacío en ambos directorios para que Python sepa que los directorios son módulos?
El esquema básico cuando no se está ejecutando desde dentro de la carpeta (es decir, tal vez de 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 a functions_etc.py
como topdir.functions_etc
o topdir.subdir.other_functions
, siempre que topdir
está en PYTHONPATH
.
ACTUALIZACIÓN: si el problema no es el archivo __init__.py
, quizás intente copiar o mover su módulo a 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 los enlaces simbólicos de Windows o su equivalente (¡yo no!), 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 al directorio de nivel de usuario de su código de desarrollo, pero en la práctica usualmente solo enlace simbólicamente mi dir de desarrollo local a site-packages - copiarlo tiene el mismo efecto.
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) Así que, como dije, use init-hook (preste atención en ''y'' el análisis de pily 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
En caso de que alguien esté buscando una forma de ejecutar pylint como una herramienta externa en PyCharm y hacer que funcione con sus entornos virtuales (por lo que llegué a esta pregunta), así es como lo resolví:
- En PyCharm> Preferencias> Herramientas> Herramientas externas, agregue o edite un elemento para la lista.
- En la configuración de la herramienta del cuadro de diálogo Editar herramienta, configure Programa para usar pylint desde el directorio del intérprete python:
$PyInterpreterDirectory$/pylint
- Establezca sus otros parámetros en el campo Parámetros, como:
--rcfile=$ProjectFileDir$/pylintrc -rn $FileDir$
- Establezca su directorio de trabajo en
$FileDir$
Ahora, al usar pylint como una herramienta externa, se ejecutará en el directorio que haya seleccionado utilizando un archivo de configuración común y se usará el intérprete configurado para su proyecto (que presumiblemente es su intérprete virtualenv).
Hay dos opciones que conozco.
Uno, cambie la variable de entorno PYTHONPATH
para incluir el directorio encima de su módulo.
Alternativamente, edite ~/.pylintrc
para incluir el directorio sobre su módulo, como este:
[MASTER]
init-hook=''import sys; sys.path.append("/path/to/root")''
(O en otra versión de pylint, el inicio-gancho requiere que cambie [General] a [MASTER])
Ambas opciones deberían funcionar.
Espero que ayude.
La clave es agregar su directorio de proyecto a sys.path
sin 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 explicarlo un poco:
re.search(r".+//" + base_dir, os.getcwd()).group()
: encuentre el directorio base de acuerdo con el archivo de ediciónos.path.join(os.getcwd(), base_dir)
: agregasys.path
asys.path
para cumplir con el entorno de línea de comandos
FYI, aquí está mi .pylintrc:
https://gist.github.com/chuyik/f0ffc41a6948b6c87c7160151ffe8c2f
La solución para alterar la ruta en init-hook
es buena, pero no me gusta el hecho de que tuve que agregar la 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.PYLINTRC
también existe y tiene el mismo valor que find_pylintrc()
.
No sé cómo funciona con WingIDE, pero para usar PyLint con Geany, configuré 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 :)
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 paquetes python. Si es así, lo agrego a PYTHONPATH. En mi caso, considero que un directorio es un paquete 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.
Tuve este mismo problema y lo solucioné instalando pylint en mi virtualenv y luego agregué un archivo .pylintrc al directorio de mi proyecto con lo siguiente en el archivo:
[Master]
init-hook=''sys.path = list(); sys.path.append("./Lib/site-packages/")''
Tuve que actualizar la variable PYTHONPATH
del sistema para agregar mi ruta de App Engine. En mi caso, tuve que editar mi archivo ~/.bashrc
y agregar la siguiente línea:
export PYTHONPATH=$PYTHONPATH:/path/to/google_appengine_folder
De hecho, intenté configurar el init-hook
primero, 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.
Una solución que acabo de descubrir es simplemente ejecutar PyLint para todo el paquete, en lugar de solo un archivo. De alguna manera, se las arregla para encontrar el módulo importado a continuación.
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 para la parte en la cláusula else
sería
from .. import one
Pensándolo bien, esto probablemente no solucionará su problema específico. No entendí bien la pregunta y pensé que two.py se estaba ejecutando como el módulo principal, pero ese no es el caso. Y considerando las diferencias en la forma en que Python 2.6 (sin importar absolute_import
de __future__
) y Python 3.x manejan las importaciones, no necesitarías hacer esto para Python 2.6 de todos modos, no creo.
Sin embargo, si finalmente cambia a Python 3 y planea usar un módulo como un módulo de paquete y como un script independiente dentro del paquete, puede ser una buena idea mantener algo así 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 one
módulo (a través de la línea de comandos, quizás), o ponga el siguiente código en alguna parte 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 al toqueteo de PYTHONPATH, solo asegúrate de que el directorio de trabajo actual sea el directorio que contiene one.py
cuando one.py
la importación.
(Mirando la respuesta de Brian, probablemente puedas asignar el código anterior a init_hook
, pero si vas a hacer eso, entonces simplemente puedes sys.path
al sys.path
que hace, que es un poco más elegante que mi solución).