PYTHONPATH เทียบกับ sys.path


94

นักพัฒนารายอื่นและฉันไม่เห็นด้วยว่าควรใช้ PYTHONPATH หรือ sys.path เพื่อให้ Python ค้นหาแพ็คเกจ Python ในไดเร็กทอรีผู้ใช้ (เช่นการพัฒนา)

เรามีโครงการ Python ที่มีโครงสร้างไดเรกทอรีทั่วไป:

Project
    setup.py
    package
        __init__.py
        lib.py
        script.py

ใน script.py import package.libเราต้องทำ เมื่อแพคเกจที่ติดตั้งในเว็บไซต์แพคเกจ script.py package.libสามารถค้นหา

อย่างไรก็ตามเมื่อทำงานจากไดเร็กทอรีผู้ใช้จำเป็นต้องทำอย่างอื่น วิธีแก้ปัญหาของฉันคือตั้งค่า PYTHONPATH ของฉันให้รวม "~ / Project" นักพัฒนารายอื่นต้องการใส่โค้ดบรรทัดนี้ไว้ที่ส่วนต้นของ script.py:

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

เพื่อให้ Python สามารถค้นหาสำเนาภายในเครื่องของpackage.lib.

ฉันคิดว่านี่เป็นความคิดที่ไม่ดีเนื่องจากบรรทัดนี้มีประโยชน์สำหรับนักพัฒนาหรือผู้ที่ทำงานจากสำเนาในเครื่องเท่านั้น แต่ฉันไม่สามารถให้เหตุผลที่ดีได้ว่าทำไมจึงเป็นความคิดที่ไม่ดี

เราควรใช้ PYTOHNPATH, sys.path หรือไม่?


4
ดูเหมือนว่าคะแนนโหวตและคำตอบจะถูกแบ่งออกอย่างเท่าเทียมกันโดยมีความเอนเอียงเล็กน้อยต่อการใช้ PYTHON_PATH แม้ว่าจะเป็นการสุ่มตัวอย่างเสียงรบกวนหรือการให้น้ำหนักโดยไม่ได้ตั้งใจจากคำถามก็ตาม
AJP

สำหรับความแตกต่างระหว่างPATHและsys.path(และทางอ้อมPYTHONPATH) โปรดดูที่stackoverflow.com/questions/25344841/sys-path-vs-path
tripleee

คำตอบ:


42

หากเหตุผลเดียวในการแก้ไขเส้นทางคือสำหรับนักพัฒนาที่ทำงานจากโครงสร้างการทำงานของพวกเขาคุณควรใช้เครื่องมือการติดตั้งเพื่อตั้งค่าสภาพแวดล้อมของคุณ Virtualenv เป็นที่นิยมอย่างมากและหากคุณใช้ setuptools คุณสามารถเรียกใช้setup.py developเพื่อกึ่งติดตั้งโครงสร้างการทำงานในการติดตั้ง Python ปัจจุบันของคุณ


11
คุณช่วยชี้แจงเพิ่มเติมเกี่ยวกับเรื่องนี้ได้ไหม แม้ว่าคุณจะยืนอยู่ในสภาพแวดล้อม conda / Virtualenv สิ่งนี้จะทำให้ dir toplevel บนเส้นทาง python ของคุณเป็นอย่างไร?
compguy24

38

ฉันเกลียด PYTHONPATH ฉันคิดว่ามันเปราะและน่ารำคาญในการตั้งค่าตามผู้ใช้แต่ละคน (โดยเฉพาะสำหรับผู้ใช้ daemon) และติดตามเมื่อโฟลเดอร์โครงการเคลื่อนที่ไปมา ฉันค่อนข้างจะตั้งค่าsys.pathในสคริปต์เรียกใช้สำหรับโครงการแบบสแตนด์อโลน

อย่างไรก็ตามsys.path.appendไม่ใช่วิธีที่จะทำ คุณสามารถรับรายการที่ซ้ำกันได้อย่างง่ายดายและจะไม่จัดเรียง.pthไฟล์ ที่ดีขึ้น site.addsitedir(และสามารถอ่านเพิ่มเติม):

และscript.pyโดยปกติจะไม่ใช่สถานที่ที่เหมาะสมกว่าในการทำเช่นนั้นเนื่องจากอยู่ในแพ็คเกจที่คุณต้องการให้พร้อมใช้งานบนเส้นทาง โมดูลห้องสมุดไม่ควรสัมผัสsys.pathตัวเองอย่างแน่นอน โดยปกติคุณจะมีสคริปต์แฮชแบงก์นอกแพ็กเกจที่คุณใช้ในการสร้างอินสแตนซ์และเรียกใช้แอปแทนและในสคริปต์ Wrapper ที่ไม่สำคัญนี้คุณจะใส่รายละเอียดการปรับใช้เช่นsys.path-frobbing


17
ปัญหาsite.addsitedirคือมันเปิดappendอยู่sys.pathซึ่งหมายความว่าแพ็คเกจที่ติดตั้งจะมีความสำคัญเหนือกว่าแพ็คเกจท้องถิ่นในการพัฒนา (และอาจเกิดการดึงขน) sys.path.insert(0...จำเป็นต้องเอาชนะสิ่งนั้น
Eli Bendersky

5
@EliBendersky: ควรจะsys.path.insert(1. stackoverflow.com/q/10095037/125507
endolith

12

โดยทั่วไปฉันจะพิจารณาการตั้งค่าตัวแปรสภาพแวดล้อม (เช่น PYTHONPATH) ว่าเป็นการปฏิบัติที่ไม่ดี แม้ว่าวิธีนี้อาจใช้ได้ดีสำหรับการแก้จุดบกพร่อง แต่การใช้สิ่งนี้เป็น
แบบฝึกหัดปกติอาจไม่ใช่ความคิดที่ดี

การใช้ตัวแปรสภาพแวดล้อมนำไปสู่สถานการณ์เช่น "มันใช้ได้สำหรับฉัน" เมื่อมีคน
อื่นรายงานปัญหาในฐานรหัส นอกจากนี้อาจมีการปฏิบัติเช่นเดียวกันกับสภาพแวดล้อมการทดสอบด้วยเช่นกันซึ่งนำไปสู่สถานการณ์เช่นการทดสอบทำงานได้ดีสำหรับนักพัฒนาโดยเฉพาะ แต่อาจล้มเหลวเมื่อมีการเปิดตัวการทดสอบ


6

นอกเหนือจากเหตุผลอื่น ๆ อีกมากมายที่กล่าวไปแล้วคุณยังสามารถชี้ให้เห็นว่าการเข้ารหัสยาก

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

เปราะเนื่องจากถือว่าตำแหน่งของ script.py - จะใช้ได้เฉพาะเมื่อ script.py อยู่ใน Project / package จะพังหากผู้ใช้ตัดสินใจย้าย / คัดลอก / symlink script.py (เกือบ) ที่อื่น


5

ฉันคิดว่าในกรณีนี้การใช้ PYTHONPATH เป็นสิ่งที่ดีกว่าส่วนใหญ่เป็นเพราะมันไม่ได้แนะนำรหัสที่ไม่จำเป็น (น่าสงสัย)

ท้ายที่สุดถ้าคุณคิดอย่างนั้นผู้ใช้ของคุณไม่ต้องการsys.pathสิ่งนั้นเพราะแพ็คเกจของคุณจะถูกติดตั้งลงในแพ็คเกจไซต์เพราะคุณจะใช้ระบบบรรจุภัณฑ์

หากผู้ใช้เลือกที่จะเรียกใช้จาก "สำเนาในเครื่อง" ตามที่คุณเรียกฉันได้สังเกตแล้วว่าการปฏิบัติตามปกติคือการระบุว่าจะต้องเพิ่มแพคเกจลงใน PYTHONPATH ด้วยตนเองหากใช้นอกไซต์แพ็คเกจ .


3

ไม่ว่าจะเป็นการแฮ็กPYTHONPATHหรือsys.pathเป็นความคิดที่ดีเนื่องจากสาเหตุที่กล่าวมาก่อนหน้านี้ และสำหรับการเชื่อมโยงโปรเจ็กต์ปัจจุบันลงในโฟลเดอร์ไซต์แพ็คเกจมีวิธีที่ดีกว่าpython setup.py developที่อธิบายไว้ที่นี่ :

pip install --editable path/to/project

หากคุณยังไม่มี setup.py ในโฟลเดอร์รูทของโปรเจ็กต์อันนี้ดีพอที่จะเริ่มต้นด้วย:

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