ข้อผิดพลาด PyLint“ ไม่สามารถนำเข้า” ได้ - จะตั้ง PYTHONPATH ได้อย่างไร?


165

ฉันใช้ 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'

ฉันจะแก้ไขสิ่งนี้ได้อย่างไร

คำตอบ:


145

มีสองตัวเลือกที่ฉันรู้

หนึ่งเปลี่ยนPYTHONPATHตัวแปรสภาพแวดล้อมเพื่อรวมไดเรกทอรีด้านบนโมดูลของคุณ

หรือมิฉะนั้น~/.pylintrcให้แก้ไขเพื่อรวมไดเรกทอรีด้านบนโมดูลของคุณดังนี้:

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

(หรือใน pylint รุ่นอื่น ๆ init-hook กำหนดให้คุณเปลี่ยน [ทั่วไป] เป็น [MASTER])

ตัวเลือกทั้งสองนี้ควรใช้งานได้

หวังว่าจะช่วย


8
เบ็ดไพลินต์นี้เป็นวิธีที่ดีที่สุดใน VScode เนื่องจาก PYTHONPATH ยังไม่ได้รับการสนับสนุนเนื่องจากมีการใช้งาน linter ในตัว
Danny Staple

2
ฉันมีปัญหาเดียวกันกับการใช้ MacVim กับ syntastic ฉันจะกำหนดค่า prosector เพื่อแก้ไขข้อผิดพลาดในการนำเข้าได้อย่างไร
Laurent

โพสต์บล็อกที่เกี่ยวข้องพร้อมรายละเอียดเพิ่มเติมเล็กน้อย
Christian Long

~/.pylintrcทำงานให้ฉันใน OSX คนอื่นไม่ทำงาน
Miquel

ไม่แน่ใจว่าทำไมนี้ไม่ได้เป็นคำตอบที่ได้รับการยอมรับ - นอกจากนี้ยังมีมูลค่าการกล่าวขวัญสำหรับผู้สะดุดเกี่ยวกับเรื่องนี้ที่คุณต้องexport PYTHONPATHเพื่อที่pylintจะเห็นมัน (อย่างน้อยในทุบตี / zsh)
มาร์โค Massenzio

43

วิธีแก้ไขเส้นทางใน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()กัน


1
ยืนยันว่านี่เป็นวิธีแก้ปัญหาสำหรับข้อผิดพลาด pylint E0611 และ E0401 สำหรับผู้ใช้ VSCode: สิ่งสำคัญคือโฟลเดอร์ที่เปิดคือ "python root folder" และ. pylintrc อยู่ในโฟลเดอร์นั้น
np8

ตรวจสอบให้แน่ใจว่าไม่มีชื่อไดเรกทอรีโมดูลของคุณเริ่มต้นด้วย.(dot)
Saw-mon และ Natalie

2
หากคุณต้องการเพิ่มโฟลเดอร์ย่อยเฉพาะ (เช่นapp) คุณสามารถใช้from 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 เป็นรายการ

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

8
ฉันดูเหมือนว่าจะได้รับการแก้ไขโดยติดตั้งpylintใน virtualenv ของฉันตามคำแนะนำนี้: plaidzooks.tumblr.com/post/36813101879
แมตต์

3
วิธีนี้ใช้งานได้ดีและควรเป็นคำตอบที่ดีที่สุด หากคุณไม่มี. pylintrc ตั้งค่าให้ทำอย่างรวดเร็วpylint --generate-rcfile > .pylintrcในโฟลเดอร์บ้านของคุณ
reka18

26

ปัญหาสามารถแก้ไขได้โดยการกำหนดค่าเส้นทาง pylint ภายใต้ venv: $ cat .vscode / settings.json

{
    "python.pythonPath": "venv/bin/python",
    "python.linting.pylintPath": "venv/bin/pylint"
}

2
สำหรับ Windows มันเป็น { "python.pythonPath": "${workspaceFolder}\\.venv\\Scripts\\python.exe" "python.linting.pylintPath": "${workspaceFolder}\\.venv\\Scripts\\pylint.exe" } เพียงเพื่อความสมบูรณ์
Roy2511

คำถามไม่ขอบรรณาธิการนี้
Ivailo Bardarov

VSCode จะแสดงข้อความนี้: The setting "python.pythonPath" defined in your settings.json is now deprecated. ถ้าฉันลบpython.pythonPathบรรทัดมันก็ยังคงใช้ได้
Jesse Aldridge

23

คุณมี__init__.pyไฟล์ว่างในทั้งสองไดเรกทอรีเพื่อให้ไพ ธ อนรู้ว่า dirs เป็นโมดูลหรือไม่?

โครงร่างพื้นฐานเมื่อคุณไม่ได้เรียกใช้จากภายในโฟลเดอร์ (เช่นอาจมาจาก pylint แม้ว่าฉันจะไม่ได้ใช้ก็ตาม) คือ:

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

นี่คือวิธีที่ล่ามหลามตระหนักของโมดูลโดยไม่มีการอ้างอิงไปยังไดเรกทอรีปัจจุบันดังนั้นหาก pylint ทำงานจากเส้นทางที่แน่นอนของตัวเองก็จะสามารถที่จะเข้าถึงfunctions_etc.pyเป็นtopdir.functions_etcหรือtopdir.subdir.other_functionsให้อยู่ในtopdirPYTHONPATH

อัปเดต: หากปัญหาไม่ใช่__init__.pyไฟล์คุณอาจลองคัดลอกหรือย้ายโมดูลของคุณไปc:\Python26\Lib\site-packages- ซึ่งเป็นสถานที่ทั่วไปในการวางแพ็คเกจเพิ่มเติมและแน่นอนจะอยู่บน pythonpath ของคุณ หากคุณรู้วิธีทำลิงก์สัญลักษณ์ของ Windows หรือสิ่งที่เทียบเท่า (ฉันทำไม่ได้!) คุณสามารถทำเช่นนั้นได้ มีตัวเลือกเพิ่มเติมมากมายที่นี่: http://docs.python.org/install/index.htmlรวมถึงตัวเลือกในการผนวก sys.path กับไดเรกทอรีระดับผู้ใช้ของรหัสการพัฒนาของคุณ แต่ในทางปฏิบัติฉันมักจะเชื่อมโยงสัญลักษณ์ การพัฒนาท้องถิ่นของฉันไปที่แพ็คเกจไซต์


1
ใช่ฉันมี__init__.pyทั้งสองไดเรกทอรี ฉันคิดว่าปัญหาคือว่า dir บนไม่ได้อยู่ใน PYTHONPATH เมื่อ PyLint ทำงานและฉันไม่แน่ใจว่าจะแก้ไขได้อย่างไร
EMP

symlink เป็นแนวคิดที่ดี แต่รองรับเฉพาะ Windows Vista เป็นต้นไปและฉันใช้ XP ฉันคิดว่าฉันสามารถลองเชื่อมโยงกับมันได้ยาก ...
30711 EMP

กำลังเชื่อมโยงใหม่: ไม่คุณไม่ควรทำ ฉันได้เล่นกับมันและในขณะที่มันใช้งานได้ดี (ในทาง) มันจะไม่ทำงานตามที่คุณคาดหวัง
shylent

Symlinks ไม่ใช่ความคิดที่ดี สิ่งนี้จะช่วยแก้ไขปัญหาในเครื่องของคุณเท่านั้น - เมื่อมีคนอื่นตรวจสอบโครงการมันจะถูกทำลายสำหรับพวกเขา
Jonathan Hartley


5

ฉันไม่ทราบวิธีการทำงานกับ WingIDE แต่สำหรับการใช้ PyLint กับ Geany ฉันได้ตั้งค่าคำสั่งภายนอกของฉันเป็น:

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

โดยที่% f เป็นชื่อไฟล์และ% d เป็นเส้นทาง อาจมีประโยชน์สำหรับใครบางคน :)


4

ฉันต้องอัปเดตPYTHONPATHตัวแปรระบบเพื่อเพิ่มเส้นทาง App Engine ของฉัน ในกรณีของฉันฉันต้องแก้ไข~/.bashrcไฟล์และเพิ่มบรรทัดต่อไปนี้:

export PYTHONPATH=$PYTHONPATH:/path/to/google_appengine_folder

อันที่จริงฉันพยายามตั้งค่าinit-hookครั้งแรก แต่นี่ไม่ได้แก้ไขปัญหาอย่างสม่ำเสมอทั่วทั้งฐานรหัสของฉัน (ไม่แน่ใจว่าทำไม) เมื่อฉันเพิ่มลงในเส้นทางของระบบ (อาจเป็นความคิดที่ดีโดยทั่วไป) ปัญหาของฉันหายไป


3

วิธีแก้ปัญหาหนึ่งที่ฉันเพิ่งค้นพบคือการเรียกใช้ PyLint จริง ๆ สำหรับแพคเกจทั้งหมดแทนที่จะเป็นไฟล์เดียว อย่างใดก็จัดการเพื่อหาโมดูลที่นำเข้ามาแล้ว


ฟังดูดี; อย่างไร
Cees Timmerman

1
@CeesTimmerman เรียกใช้pylint ... dirจากโฟลเดอร์หลัก สิ่งนี้จำเป็นต้อง__init__.pyมีอยู่ในแต่ละโฟลเดอร์ย่อยที่มี.pyไฟล์
yugr

3

ลอง

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สิ่งที่เขาทำซึ่งสง่างามกว่าโซลูชันของฉันเล็กน้อย)


2

กุญแจสำคัญคือการเพิ่มไดเรกทอรีโครงการของคุณไป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ตอบสนองสภาพแวดล้อมของบรรทัดคำสั่ง


FYI นี่คือ. pylintrc ของฉัน:

https://gist.github.com/chuyik/f0ffc41a6948b6c87c7160151ffe8c2f


2

ฉันมีปัญหาเดียวกันนี้และแก้ไขได้โดยการติดตั้ง pylint ใน virtualenv ของฉันจากนั้นเพิ่มไฟล์. pylintrc ไปยังไดเรกทอรีโครงการของฉันด้วยสิ่งต่อไปนี้ในไฟล์:

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

ฉันต้องยืนยันว่านี่เป็นการกำจัดข้อผิดพลาด pylint E0611 แต่ข้อผิดพลาด E0401 ยังคงอยู่
np8

1

อาจด้วยการผนวก dir ภายใน PYTHONPATH ด้วยตนเอง

sys.path.append(dirname)

อืม แต่ที่ไหนที่คุณจะวางรหัสนั้น ที่ด้านบนของแต่ละไฟล์และทุก ๆ ฉันคิดว่ามันใช้งานได้ แต่มันค่อนข้างแฮ็คเพียงเพื่อให้ PyLint ทำงาน
EMP

@Evgeny: ดูคำตอบที่ Brian M. Hunt โพสต์เมื่อเร็ว ๆ นี้
JAB

และการเพิ่มสิ่งนี้ไว้ที่ด้านบนของไฟล์ทุกไฟล์ไม่สามารถทำได้ด้วยเหตุผลบางอย่าง - PyLint ดูเหมือนจะมีเนื้อหาสมบูรณ์แบบที่จะไม่สนใจการแก้ไข sys.path ที่ทำจากภายในโมดูลที่กำลังสแกน ฉันไม่ได้สนใจที่จะค้นคว้าว่าทำไมถึงยัง ...
javawizard

1

ฉันมีปัญหาเดียวกันและเนื่องจากฉันไม่สามารถหาคำตอบได้ฉันหวังว่านี่จะช่วยทุกคนที่มีปัญหาคล้ายกัน

ฉันใช้ flymake กับ epylint โดยทั่วไปสิ่งที่ฉันทำคือเพิ่ม dired-mode-hook ที่ตรวจสอบว่าไดเรกทอรี dired เป็นไดเรกทอรีแพคเกจหลาม ถ้าเป็นฉันจะเพิ่มลงใน PYTHONPATH ในกรณีของฉันฉันถือว่าไดเรกทอรีเป็นแพคเกจหลามถ้ามันมีไฟล์ชื่อ "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)

หวังว่านี่จะช่วยได้


1

ในกรณีที่ทุกคนกำลังมองหาวิธีการเรียกใช้ pylint เป็นเครื่องมือภายนอกใน PyCharm และทำงานกับสภาพแวดล้อมเสมือนของพวกเขา (ทำไมฉันถึงคำถามนี้) นี่คือวิธีที่ฉันแก้ไข:

  1. ใน PyCharm> การตั้งค่า> เครื่องมือ> เครื่องมือภายนอกเพิ่มหรือแก้ไขรายการสำหรับ pylint
  2. ในการตั้งค่าเครื่องมือของไดอะล็อกเครื่องมือแก้ไขให้ตั้งค่าโปรแกรมให้ใช้ pylint จากไดเรกทอรีล่ามไพ ธ อน: $PyInterpreterDirectory$/pylint
  3. ตั้งค่าพารามิเตอร์อื่น ๆ ของคุณในฟิลด์พารามิเตอร์เช่น: --rcfile=$ProjectFileDir$/pylintrc -r n $FileDir$
  4. ตั้งค่าไดเรกทอรีการทำงานของคุณเป็น $FileDir$

ตอนนี้การใช้ pylint เป็นเครื่องมือภายนอกจะเรียกใช้ pylint ในทุกไดเรกทอรีที่คุณเลือกใช้ไฟล์กำหนดค่าทั่วไปและใช้สิ่งใดก็ตามที่มีการกำหนดค่าล่ามสำหรับโครงการของคุณ (ซึ่งน่าจะเป็นล่าม virtualenv ของคุณ)


1

นี่เป็นคำถามเก่า แต่ไม่มีคำตอบที่ยอมรับดังนั้นฉันจะแนะนำสิ่งนี้: เปลี่ยนคำสั่งการนำเข้าใน two.py เพื่ออ่าน:

from .. import one

ในสภาพแวดล้อมปัจจุบันของฉัน (Python 3.6, VSCode โดยใช้ pylint 2.3.1) สิ่งนี้จะล้างคำสั่งที่ถูกตั้งค่าสถานะ


1

ผมพบว่าดีคำตอบ แก้ไข 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'))"

1

เมื่อคุณติดตั้ง Python คุณสามารถตั้งค่าพา ธ หากเส้นทางถูกกำหนดไว้แล้วสิ่งที่คุณสามารถทำได้คือภายในรหัส VS, กด Ctrl + Shift + P แล้วพิมพ์ Python: เลือก Interpreter และเลือก Python เวอร์ชันที่อัพเดต ติดตามลิงค์นี้สำหรับข้อมูลเพิ่มเติมhttps://code.visualstudio.com/docs/python/environment


0

ถ้าคุณใช้ vscode ตรวจสอบให้แน่ใจว่าไดเรกทอรีแพ็คเกจของคุณอยู่นอกไดเรกทอรี _pychache__


นอกจากนี้ด้วยรหัส VS ดูเหมือนว่ามีปัญหาที่อาจเกิดขึ้นกับจุดในชื่อโฟลเดอร์: github.com/PyCQA/pylint/issues/2182
Eric Burel

0

หากคุณใช้ Cython ใน Linux ฉันจะแก้ไขการลบmodule.cpython-XXm-X-linux-gnu.soไฟล์ในไดเรกทอรีเป้าหมายโครงการของฉัน


0

เพียงเพิ่มรหัสนี้ในไฟล์. vscode / settings.json

, "python.linting.pylintPath": "venv / bin / pylint"

สิ่งนี้จะแจ้งตำแหน่งของ pylint (ซึ่งเป็นตัวตรวจสอบข้อผิดพลาดสำหรับ python)


-1

สวัสดีฉันสามารถนำเข้าแพคเกจจากไดเรกทอรีที่แตกต่างกัน ฉันเพิ่งทำสิ่งต่อไปนี้: หมายเหตุ: ฉันใช้ VScode

ขั้นตอนในการสร้างแพ็คเกจ Python การทำงานกับแพ็คเกจ Python นั้นง่ายมาก สิ่งที่คุณต้องทำคือ:

สร้างไดเรกทอรีและตั้งชื่อแพ็คเกจของคุณ ใส่ชั้นเรียนของคุณลงไป สร้างไฟล์init .py ในไดเรกทอรี

ตัวอย่างเช่นคุณมีโฟลเดอร์ชื่อ Framework ที่คุณเก็บคลาสแบบกำหนดเองทั้งหมดไว้ที่นั่นและงานของคุณคือสร้างไฟล์init .py ภายในโฟลเดอร์ชื่อ Framework

และในขณะที่นำเข้าคุณจะต้องนำเข้าในลักษณะนี้ --->

จากฐานการนำเข้า Framework

ดังนั้นข้อผิดพลาด E0401 จึงหายไป Framework เป็นโฟลเดอร์ที่คุณเพิ่งสร้างinit .py และ base เป็นโมดูลที่คุณกำหนดเองซึ่งคุณต้องนำเข้าและทำงานตามหวังว่าจะช่วยได้ !!!!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.