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'
How do I fix this?
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.
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()
.
.
(dot).
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'))
init-hook="from pylint.config import find_pylintrc; import os, sys; sys.path.append(os.path.join(os.path.dirname(find_pylintrc()),".."))"
The problem can be solved by configuring pylint path under venv: $ cat .vscode/settings.json
{
"python.pythonPath": "venv/bin/python",
"python.linting.pylintPath": "venv/bin/pylint"
}
{ "python.pythonPath": "${workspaceFolder}\\.venv\\Scripts\\python.exe" "python.linting.pylintPath": "${workspaceFolder}\\.venv\\Scripts\\pylint.exe" }
Just for completeness.
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.
.venv/
by default): "python.linting.pylintPath": "${workspaceFolder}/.venv/bin/pylint",
"python.linting.pylintPath": "venv/bin/pylint"
was enough to me, although I already had pythonPath set
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.
__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.
general answer for this question I found on this page PLEASE NOT OPEN, SITE IS BUGED
create .pylintrc
and add
[MASTER]
init-hook="from pylint.config import find_pylintrc;
import os, sys; sys.path.append(os.path.dirname(find_pylintrc()))"
1) sys.path is a list.
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])'
or
[Master]
init-hook='sys.path = list(); sys.path.append("/path/to/foo")'
.. and
pylint --rcfile /path/to/pylintrc /path/to/module.py
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
I don't know how it works with WingIDE, but for using PyLint with Geany, I set my external command to:
PYTHONPATH=${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 :)
Try
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 from .. import one
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
in mind.
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 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:
export PYTHONPATH=$PYTHONPATH:/path/to/google_appengine_folder
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.
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'))"
When you install Python, you can set up the path. If path is already defined then what you can do is within VS Code, hit Ctrl+Shift+P and type Python: Select Interpreter and select updated version of Python. Follow this link for more information, https://code.visualstudio.com/docs/python/environments
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.
__import__
function which might be handy here
One workaround that I only just discovered is to actually just run PyLint for the entire package, rather than a single file. Somehow, it manages to find imported module then.
pylint ... dir
from parent folder. This requires __init__.py
to be present in each subfolder with .py
files.
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)
Hope this helps.
The key is to add your project directory to sys.path
without considering about the env variable.
For someone who use VSCode, here's a one-line solution for you if there's a base directory of your project:
[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)'
Let me explain it a little bit:
re.search(r".+\/" + base_dir, os.getcwd()).group(): find base directory according to the editing file
os.path.join(os.getcwd(), base_dir): add cwd to sys.path to meet command line environment
FYI, here's my .pylintrc:
https://gist.github.com/chuyik/f0ffc41a6948b6c87c7160151ffe8c2f
First, go to your VS Code then press "ctrl + shift + p"
Then search settings.json
Then paste the below code inside the settings.jason.I hope the problem will be solved.
{
"python.pythonPath": "venv/bin/python",
"python.linting.pylintPath": "venv/bin/pylint"
}
I got this error when trying to submit a PR. What I end up doing is just to add #pylint: disable=E0401 on the same line where "import" happens.
This helps me to pass the auto test.
Maybe by manually appending the dir inside the PYTHONPATH?
sys.path.append(dirname)
In case anybody is looking for a way to run pylint as an external tool in PyCharm and have it work with their virtual environments (why I came to this question), here's how I solved it:
In PyCharm > Preferences > Tools > External Tools, Add or Edit an item for pylint. In the Tool Settings of the Edit Tool dialog, set Program to use pylint from the python interpreter directory: $PyInterpreterDirectory$/pylint Set your other parameters in the Parameters field, like: --rcfile=$ProjectFileDir$/pylintrc -r n $FileDir$ Set your working directory to $FileDir$
Now using pylint as an external tool will run pylint on whatever directory you have selected using a common config file and use whatever interpreter is configured for your project (which presumably is your virtualenv interpreter).
This is an old question but has no accepted answer, so I'll suggest this: change the import statement in two.py to read:
from .. import one
In my current environment (Python 3.6, VSCode using pylint 2.3.1) this clears the flagged statement.
Mac user: If you're using Anaconda 3 w/ vsCode and have multiple environments, pointing to the following path via settings.json
for vsCode works as well:
{
"python.pythonPath": "/Users/username/opt/anaconda3/bin/python",
"python.linting.pylintPath": "/Users/username/opt/anaconda3/bin/python"
}
If you are using Windows:
get the path of the python.exe inside the virtual environment you just created
it should be like this Z:\YourProjectFolder\Scripts\python.exe
then go to your vscode and edit the user settings.json
add this line: "python.pythonPath": "Z:\\YourProjectFolder\\Scripts\\python.exe"
save it and that should fix the issue
NOTE: the double backslash instead of single when putting it to the json file
{
"python.pythonPath": "Z:\\YourProjectFolder\\Scripts\\python.exe"
}
Hello i was able to import the packages from different directory. I just did the following: Note: I am using VScode
Steps to Create a Python Package Working with Python packages is really simple. All you need to do is:
Create a directory and give it your package's name.
Put your classes in it.
Create a __init__.py file in the directory
For example: you have a folder called Framework where you are keeping all the custom classes there and your job is to just create a __init__.py file inside the folder named Framework.
And while importing you need to import in this fashion--->
from Framework import base
so the E0401 error disappears Framework is the folder where you just created __init__.py and base is your custom module which you are required to import into and work upon Hope it helps!!!!
this all work for me!
.pylintrc
[MASTER]
; init-hook='import sys; sys.path.append("./venv/lib/python3.8/site-packages")'
; or
init-hook='import sys; sys.path.append(f"./venv/lib/python{sys.version[:3]}/site-packages");'
; or
;init-hook='from distutils.sysconfig import get_python_lib; sys.path.append(get_python_lib())'
; or
; init-hook='import site; sys.path.append(site.getsitepackages()[0])'
if you using vscode,make sure your package directory is out of the _pychache__ directory.
If you are using Cython in Linux, I resolved removing module.cpython-XXm-X-linux-gnu.so
files in my project target directory.
I found this worked nicely in my local .pylintrc
file with a pipenv virtual environment:
[MASTER]
init-hook='import site; sys.path += site.getsitepackages()'
See this post for info about site packages.
just add this code in .vscode/settings.json
file
,"python.linting.pylintPath": "venv/bin/pylint"
This will notify the location of pylint(which is an error checker for python)
venv
is your local virtual environment directory. You probably want to add ${workspaceFolder}
at the start of the path.
Success story sharing
~/.pylintrc
worked for me on OSX, the other didn't workexport PYTHONPATH
so thatpylint
will see it (at least, in bash/zsh)