PyLint "Невозможно импортировать" ошибка - как установить PYTHONPATH?
Я использую PyLint изнутри Wing IDE в Windows. У меня есть подкаталог (пакет) в моем проекте, и внутри пакета я импортирую модуль с верхнего уровня, т.е.
__init__.py
myapp.py
one.py
subdir\
__init__.py
two.py
внутри two.py
я имею import one
и это прекрасно работает во время выполнения, потому что каталог верхнего уровня (из которого myapp.py
находится в пути Python. Однако, когда я запускаю PyLint на two.py, он выдает ошибку:
F0401: Unable to import 'one'
Как это исправить?
34 ответа
Есть два варианта, которые я знаю.
Один, изменить PYTHONPATH
переменная окружения, чтобы включить каталог над вашим модулем.
Или отредактируйте ~/.pylintrc
чтобы включить каталог над вашим модулем, вот так:
[MASTER]
init-hook='import sys; sys.path.append("/path/to/root")'
(Или в другой версии pylint, init-hook требует от вас изменить [General] на [MASTER])
Оба эти варианта должны работать.
Надеюсь, это поможет.
Решение изменить путь в init-hook
это хорошо, но мне не нравится тот факт, что мне пришлось добавить абсолютный путь, в результате я не могу поделиться этим файлом pylintrc среди разработчиков проекта. Это решение, использующее относительный путь к файлу pylintrc, работает лучше для меня:
[MASTER]
init-hook="from pylint.config import find_pylintrc; import os, sys; sys.path.append(os.path.dirname(find_pylintrc()))"
Обратите внимание, что pylint.config.PYLINTRC
также существует и имеет то же значение, что и find_pylintrc()
,
Проблема может быть решена путем настройки пути pylint под venv: $ cat .vscode/settings.json
{
"python.pythonPath": "venv/bin/python",
"python.linting.pylintPath": "venv/bin/pylint"
}
Общий ответ на этот вопрос я нашел на этой странице, ПОЖАЛУЙСТА, НЕ ОТКРЫВАЙТЕ, САЙТ ИСПОЛЬЗУЕТСЯ
Создайте .pylintrc
и добавить
[MASTER]
init-hook="from pylint.config import find_pylintrc;
import os, sys; sys.path.append(os.path.dirname(find_pylintrc()))"
Я добавил новый файл
pylintrc
в корневом каталоге проекта с
[MASTER]
init-hook='import sys; sys.path.append(".")'
и это работает для меня в PyCharm IDE
У вас есть пустой __init__.py
файл в обоих каталогах, чтобы Python знал, что каталоги являются модулями?
Основная схема, когда вы не запускаете из папки (то есть, возможно, из Pylint, хотя я не использовал это):
topdir\
__init__.py
functions_etc.py
subdir\
__init__.py
other_functions.py
Вот как интерпретатор Python узнает о модуле без ссылки на текущий каталог, поэтому, если Pylint работает по своему собственному абсолютному пути, он сможет получить доступ functions_etc.py
как topdir.functions_etc
или же topdir.subdir.other_functions
, предоставлена topdir
на PYTHONPATH
,
ОБНОВЛЕНИЕ: Если проблема не в __init__.py
файл, возможно просто попробуйте скопировать или переместить ваш модуль в c:\Python26\Lib\site-packages
- это обычное место для размещения дополнительных пакетов, и оно обязательно будет на вашем pythonpath. Если вы знаете, как создавать символические ссылки Windows или аналогичные (я не знаю!), Вы можете сделать это вместо этого. Здесь есть еще много вариантов http://docs.python.org/install/index.html, включая возможность добавления sys.path к каталогу уровня пользователя вашего кода разработки, но на практике я обычно просто символически связываю мой локальный каталог разработки для пакетов сайта - копирование его имеет тот же эффект.
1) sys.path - это список.
2) Иногда проблема в том, что sys.path не является вашим virtualenv.path, и вы хотите использовать pylint в вашем virtualenv.
3) Как сказано, используйте init-hook (обратите внимание на 'и "синтаксический анализ pylint)
[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
Я не знаю, как это работает с WingIDE, но для использования PyLint с Geany я установил свою внешнюю команду на:
PYTHONPATH=${PYTHONPATH}:$(dirname %d) pylint --output-format=parseable --reports=n "%f"
где%f - имя файла, а%d - путь. Может быть кому-то пригодится:)
Мне пришлось обновить систему PYTHONPATH
переменная, чтобы добавить мой путь к App Engine. В моем случае мне просто нужно было отредактировать ~/.bashrc
файл и добавьте следующую строку:
export PYTHONPATH=$PYTHONPATH:/path/to/google_appengine_folder
На самом деле, я попытался установить init-hook
во-первых, но это не решило проблему последовательно по всей моей кодовой базе (не знаю почему). Как только я добавил его в системный путь (вероятно, хорошая идея в целом), мои проблемы исчезли.
Если вы хотите выйти из текущего модуля / файла, который был передан
pylint
ищем корень модуля, это сделает это.
[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]
Если у вас есть модуль Python
~/code/mymodule/
, с макетом каталога верхнего уровня, подобным этому
~/code/mymodule/
├── .pylintrc
├── mymodule/
│ └── src.py
└── tests/
└── test_src.py
Тогда это добавит
~/code/mymodule/
на ваш путь к Python и разрешите запуск pylint в вашей среде IDE, даже если вы импортируете
mymodule.src
в
tests/test_src.py
.
Вы можете обменять чек на
.pylintrc
вместо этого, но каталог git обычно то, что вам нужно, когда дело доходит до корня модуля python.
Прежде чем спросить
Ответы с использованием
import sys, os; sys.path.append(...)
не хватает чего-то, что оправдывает формат моего ответа. Обычно я не пишу код таким образом, но в этом случае вы столкнулись с ограничениями парсера и оценщика конфигурации pylintrc. Это буквально бежит
exec
в контексте обратного вызова init_hook, поэтому любая попытка импорта
pathlib
использовать многострочные операторы, сохранять что-либо в переменных и т. д. не будут работать.
Менее отвратительная форма моего кода может выглядеть так:
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])
Хотел бы я использовать
pathlib.Path(filename).parents
так было бы намного проще.
Я нашел хороший ответ. Отредактируйте свой pylintrc и добавьте следующее в мастер
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 __name__ == '__main__':
from [whatever the name of your package is] import one
else:
import one
Обратите внимание, что в Python 3 синтаксис для части вelse
пункт будет
from .. import one
Если подумать, это, вероятно, не решит вашу конкретную проблему. Я неправильно понял вопрос и подумал, что two.py запускается как основной модуль, но это не так. И учитывая различия в способе Python 2.6 (без импорта absolute_import
от __future__
) и Python 3.x обрабатывают импорт, в любом случае вам не нужно делать это для Python 2.6, я не думаю.
Тем не менее, если вы в конечном итоге переключитесь на Python 3 и планируете использовать модуль как пакетный модуль и как отдельный скрипт внутри пакета, возможно, будет хорошей идеей сохранить что-то вроде
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
в уме.
РЕДАКТИРОВАТЬ: И теперь для возможного решения вашей актуальной проблемы. Запустите PyLint из каталога, содержащего one
модуль (возможно, через командную строку) или поместите следующий код куда-нибудь при запуске PyLint:
import os
olddir = os.getcwd()
os.chdir([path_of_directory_containing_module_one])
import one
os.chdir(olddir)
В основном, в качестве альтернативы возни с PYTHONPATH, просто убедитесь, что текущий рабочий каталог - это каталог, содержащий one.py
когда вы делаете импорт.
(Глядя на ответ Брайана, вы, вероятно, могли бы присвоить предыдущий код init_hook
, но если вы собираетесь это сделать, то вы можете просто добавить sys.path
что он делает, что немного более элегантно, чем мое решение.)
У меня была такая же проблема, и я исправил ее, установив pylint в моем virtualenv, а затем добавив файл.pylintrc в каталог моего проекта, добавив в него следующее:
[Master]
init-hook='sys.path = list(); sys.path.append("./Lib/site-packages/")'
У меня была такая же проблема, и так как я не мог найти ответ, я надеюсь, что это может помочь любому с подобной проблемой.
Я использую мухи с эпилинтом. По сути, я добавил хук dired-mode, который проверял, является ли каталог dired каталогом пакета python. Если это так, я добавляю его в PYTHONPATH. В моем случае я рассматриваю каталог как пакет python, если он содержит файл с именем "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)
Надеюсь это поможет.
Я получил эту ошибку при попытке отправить PR. В итоге я просто добавляю #pylint: disable=E0401 в ту же строку, где происходит «импорт».
Это помогает мне пройти автотест.
Ключ должен добавить каталог вашего проекта в sys.path
без учета переменной env.
Для тех, кто использует VSCode, вот решение для одной строки, если есть базовый каталог вашего проекта:
[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)'
Позвольте мне объяснить это немного:
re.search(r".+\/" + base_dir, os.getcwd()).group()
: найти базовый каталог в соответствии с файлом редактированияos.path.join(os.getcwd(), base_dir)
: добавлятьcwd
вsys.path
встретить среду командной строки
К вашему сведению, вот мой.pylintrc:
https://gist.github.com/chuyik/f0ffc41a6948b6c87c7160151ffe8c2f
Один из обходных путей, который я только что обнаружил, - это просто запустить PyLint для всего пакета, а не для одного файла. Каким-то образом удается найти импортированный модуль.
Сначала перейдите в свой код VS и нажмите "ctrl + shift + p".
Затем найдите settings.json
Затем вставьте приведенный ниже код в файл settings.jason. Надеюсь, проблема будет решена.
{
"python.pythonPath": "venv/bin/python",
"python.linting.pylintPath": "venv/bin/pylint"
}
При установке Python вы можете указать путь. Если путь уже определен, то все, что вы можете сделать, находится в VS Code, нажмите Ctrl+Shift+P и введите Python: выберите Interpreter и выберите обновленную версию Python. Перейдите по этой ссылке для получения дополнительной информации https://code.visualstudio.com/docs/python/environments
это все работает для меня!
.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])'
Это старый вопрос, но на него нет принятого ответа, поэтому я предлагаю следующее: измените оператор импорта в two.py, чтобы он читался:
from .. import one
В моей текущей среде (Python 3.6, VSCode с использованием pylint 2.3.1) это очищает помеченный оператор.
Я обнаружил, что это хорошо работает в моем местном
.pylintrc
файл с виртуальной средой pipenv:
[MASTER]
init-hook='import site; sys.path += site.getsitepackages()'
См. Этот пост для получения информации о пакетах сайта.
Здравствуйте, я смог импортировать пакеты из другого каталога. Я просто сделал следующее: Примечание: я использую VScode
Шаги для создания пакета Python Работать с пакетами Python действительно просто. Все, что вам нужно сделать, это:
Создайте каталог и дайте ему имя вашего пакета. Поместите свои классы в это. Создайте файл init.py в каталоге
Например: у вас есть папка с именем Framework, в которой вы храните все пользовательские классы, и ваша задача - просто создать файл init.py внутри папки с именем Framework.
И при импорте нужно импортировать таким образом --->
из базы импорта Framework
ошибка E0401 исчезает. Framework - это папка, в которой вы только что создали init.py, а base - ваш пользовательский модуль, в который вы должны импортировать и работать над ним. Надеюсь, это поможет!!!!
Если вы используете Windows:
- получить путь к python.exe внутри виртуальной среды, которую вы только что создали
- это должно быть так
Z:\YourProjectFolder\Scripts\python.exe
- затем перейдите к своему vscode и отредактируйте пользователя
settings.json
- добавьте эту строку:
"python.pythonPath": "Z:\\YourProjectFolder\\Scripts\\python.exe"
- сохраните его, и это должно решить проблему
- ПРИМЕЧАНИЕ: двойная обратная косая черта вместо одинарной при помещении в файл json
{
"python.pythonPath": "Z:\\YourProjectFolder\\Scripts\\python.exe"
}
Может быть, вручную добавив dir в PYTHONPATH?
sys.path.append(dirname)
Если кто-то ищет способ запустить Pylint как внешний инструмент в PyCharm и заставить его работать со своими виртуальными средами (почему я пришел к этому вопросу), вот как я решил это:
- В PyCharm > "Настройки"> "Инструменты"> "Внешние инструменты" добавьте или измените элемент для столбца.
- В настройках инструмента диалогового окна "Редактировать инструмент" задайте для программы использование pylint из каталога интерпретатора python:
$PyInterpreterDirectory$/pylint
- Установите другие параметры в поле "Параметры", например:
--rcfile=$ProjectFileDir$/pylintrc -r n $FileDir$
- Установите ваш рабочий каталог на
$FileDir$
Теперь использование pylint в качестве внешнего инструмента будет запускать pylint в любом каталоге, который вы выбрали, используя общий файл конфигурации, и использовать любой интерпретатор, настроенный для вашего проекта (который, вероятно, является вашим интерпретатором virtualenv).
Пользователь Mac: если вы используете Anaconda 3 с vsCode и имеете несколько сред, укажите следующий путь через
settings.json
для vsCode также работает:
{
"python.pythonPath": "/Users/username/opt/anaconda3/bin/python",
"python.linting.pylintPath": "/Users/username/opt/anaconda3/bin/python"
}
Просто добавьте этот код в файл.vscode/settings.json
,"python.linting.pylintPath": "venv/bin/pylint"
Это уведомит о местоположении pylint(который является средством проверки ошибок для python)
Бросив еще один потенциальный ответ в кучу. Я пробовал много решений, представленных здесь. Либо я сделал их неправильно, либо моя ошибка импорта pylint была вызвана чем-то другим. Несмотря на это, мое решение было довольно простым.
Решение: переустановите любой пакет (пакет PyPi, а не пакет pip), который содержит все модули, которые вы не можете импортировать, а затем переустановите pylint, чтобы pylint и эти модули были установлены одним и тем же pip.
Для меня наличие правильного каталога не сработало. Я получил эту идею, прочитав другую ветку о его проблеме.
Если вы используете Cython в Linux, я решил удалить module.cpython-XXm-X-linux-gnu.so
файлы в моем целевом каталоге проекта.