Pylint import error python

PyLint «Unable to import» error — how to set PYTHONPATH?

I’m running PyLint from inside Wing IDE on Windows. I have a sub-directory (package) in my project and inside the package I import a module from the top level, ie.

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

Inside two.py I have import one and this works fine at runtime, because the top-level directory (from which myapp.py is run) is in the Python path. However, when I run PyLint on two.py it gives me an error:

F0401: Unable to import 'one' 

34 Answers 34

There are two options I’m aware of.

One, change the PYTHONPATH environment variable to include the directory above your module.

Alternatively, edit ~/.pylintrc to include the directory above your module, like this:

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

(Or in other version of pylint, the init-hook requires you to change [General] to [MASTER])

Both of these options ought to work.

This pylint hook is currently the best way in VScode as PYTHONPATH isn’t yet supported for it’s built in linter usage.

I have the same issue using MacVim with syntastic. How can I configure prosector to fix the import error ?

The solution to alter path in init-hook is good, but I dislike the fact that I had to add absolute path there, as result I can not share this pylintrc file among the developers of the project. This solution using relative path to pylintrc file works better for me:

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

Note that pylint.config.PYLINTRC also exists and has the same value as find_pylintrc() .

Confirming that this really did supply the solution for E0611 and E0401 pylint errors. For VSCode users: It is important the the opened folder is the «python root folder», and that the .pylintrc is in that folder.

if you want to add a specific sub-folder (i.e. app ) you can use from pylint.config import find_pylintrc; import os, sys; sys.path.append(os.path.join(os.path.dirname(find_pylintrc()), ‘app’))

In my setup the package in question was outside the root of the project, therefore my line looks like this: init-hook=»from pylint.config import find_pylintrc; import os, sys; sys.path.append(os.path.join(os.path.dirname(find_pylintrc()),»..»))»

This won’t work if you are using pyproject.toml file, use this instead: from pylint.config import find_default_config_files; import os, sys; sys.path.append(os.path.dirname(next(find_default_config_files())))

The problem can be solved by configuring pylint path under venv: $ cat .vscode/settings.json

For Windows it’s < "python.pythonPath": "$\\.venv\\Scripts\\python.exe» «python.linting.pylintPath»: «$\\.venv\\Scripts\\pylint.exe» > Just for completeness.

VSCode now shows this message: The setting «python.pythonPath» defined in your settings.json is now deprecated. If I delete the python.pythonPath line it still seems to work though.

Simple as that. That sounds way better than altering import paths. That works perfectly for anyone using poetry (which creates its virtual environment in .venv/ by default): «python.linting.pylintPath»: «$/.venv/bin/pylint»,

Adding «python.linting.pylintPath»: «venv/bin/pylint» was enough to me, although I already had pythonPath set

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

I would add that this file should be placed in the directory that you want added to PYTHONPATH. Also, this only worked for me if the double-quoted commands are on a single line instead of two, as above.

Do you have an empty __init__.py file in both directories to let python know that the dirs are modules?

The basic outline when you are not running from within the folder (ie maybe from pylint’s, though I haven’t used that) is:

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

This is how the python interpreter is aware of the module without reference to the current directory, so if pylint is running from its own absolute path it will be able to access functions_etc.py as topdir.functions_etc or topdir.subdir.other_functions , provided topdir is on the PYTHONPATH .

UPDATE: If the problem is not the __init__.py file, maybe just try copying or moving your module to c:\Python26\Lib\site-packages — that is a common place to put additional packages, and will definitely be on your pythonpath. If you know how to do Windows symbolic links or the equivalent (I don’t!), you could do that instead. There are many more options here: http://docs.python.org/install/index.html, including the option of appending sys.path with the user-level directory of your development code, but in practice I usually just symbolically link my local development dir to site-packages — copying it over has the same effect.

Yes, I do have __init__.py in both directories. I think the problem is that the top dir is NOT in PYTHONPATH when PyLint runs and I’m not sure how to fix that.

The symlink is a good idea, but it’s only supported from Windows Vista onwards and I’m running XP. I suppose I could try hard-linking it.

re hardlinking: No, you better don’t do it. I’ve played with it and, while it certainly works (in a way), it will not work as you expect.

Symlinks are not a good idea. This only fixes the problem on your machine — when someone else checks out the project, it will be broken for them.

I’ve added a new file pylintrc in the project’s root directory with

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

and it works for me in PyCharm IDE

2) The problem is sometimes the sys.path is not your virtualenv.path and you want to use pylint in your virtualenv

3) So like said, use init-hook (pay attention in ‘ and » the parse of pylint is strict)

[Master] init-hook='sys.path = ["/path/myapps/bin/", "/path/to/myapps/lib/python3.3/site-packages/", . many paths here])' 
[Master] init-hook='sys.path = list(); sys.path.append("/path/to/foo")' 
pylint --rcfile /path/to/pylintrc /path/to/module.py 

I don’t know how it works with WingIDE, but for using PyLint with Geany, I set my external command to:

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

where %f is the filename, and %d is the path. Might be useful for someone 🙂

I had to update the system PYTHONPATH variable to add my App Engine path. In my case I just had to edit my ~/.bashrc file and add the following line:

In fact, I tried setting the init-hook first but this did not resolve the issue consistently across my code base (not sure why). Once I added it to the system path (probably a good idea in general) my issues went away.

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

Note that in Python 3, the syntax for the part in the else clause would be

On second thought, this probably won’t fix your specific problem. I misunderstood the question and thought that two.py was being run as the main module, but that is not the case. And considering the differences in the way Python 2.6 (without importing absolute_import from __future__ ) and Python 3.x handle imports, you wouldn’t need to do this for Python 2.6 anyway, I don’t think.

Still, if you do eventually switch to Python 3 and plan on using a module as both a package module and as a standalone script inside the package, it may be a good idea to keep something like

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 

EDIT: And now for a possible solution to your actual problem. Either run PyLint from the directory containing your one module (via the command line, perhaps), or put the following code somewhere when running PyLint:

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

Basically, as an alternative to fiddling with PYTHONPATH, just make sure the current working directory is the directory containing one.py when you do the import.

(Looking at Brian’s answer, you could probably assign the previous code to init_hook , but if you’re going to do that then you could simply do the appending to sys.path that he does, which is slightly more elegant than my solution.)

I had this same issue and fixed it by installing pylint in my virtualenv and then adding a .pylintrc file to my project directory with the following in the file:

[Master] init-hook='sys.path = list(); sys.path.append("./Lib/site-packages/")' 

I found a nice answer. Edit your pylintrc and add the following in 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'))" 

If you want to walk up from the current module/file that was handed to pylint looking for the root of the module, this will do it.

[MASTER] init-hook=sys.path += [os.path.abspath(os.path.join(os.path.sep, *sys.argv[-1].split(os.sep)[:i])) for i, _ in enumerate(sys.argv[-1].split(os.sep)) if os.path.isdir(os.path.abspath(os.path.join(os.path.sep, *sys.argv[-1].split(os.sep)[:i], '.git')))][::-1] 

If you have a python module ~/code/mymodule/ , with a top-level directory layout like this

~/code/mymodule/ ├── .pylintrc ├── mymodule/ │ └── src.py └── tests/ └── test_src.py 

Then this will add ~/code/mymodule/ to your python path and allow for pylint to run in your IDE, even if you’re importing mymodule.src in tests/test_src.py .

You could swap out a check for a .pylintrc instead but a git directory is usually what you want when it comes to the root of a python module.

Before you ask

The answers using import sys, os; sys.path.append(. ) are missing something that justifies the format of my answer. I don’t normally write code that way, but in this case you’re stuck dealing with the limitations of the pylintrc config parser and evaluator. It literally runs exec in the context of the init_hook callback so any attempt to import pathlib , use multi-line statements, store something into variables, etc., won’t work.

A less disgusting form of my code might look like this:

import os import sys def look_for_git_dirs(filename): has_git_dir = [] filename_parts = filename.split(os.sep) for i, _ in enumerate(filename_parts): filename_part = os.path.abspath(os.path.join(os.path.sep, *filename_parts[:i])) if os.path.isdir(os.path.join(filename_part, '.git')): has_git_dir.append(filename_part) return has_git_dir[::-1] # don't use .append() in case there's < 1 or >1 matches found sys.path += look_for_git_dirs(sys.argv[-1]) 

I wish I could have used pathlib.Path(filename).parents it would have made things much easier.

Although not really suggested, it is possible to import using __import__ function which might be handy here

I had the same problem and since i could not find a answer I hope this can help anyone with a similar problem.

I use flymake with epylint. Basically what i did was add a dired-mode-hook that check if the dired directory is a python package directory. If it is I add it to the PYTHONPATH. In my case I consider a directory to be a python package if it contains a file named «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) 

Источник

Читайте также:  Php string to translit
Оцените статью