ทำไม Python ไม่พบวัตถุที่แชร์ที่อยู่ในไดเร็กทอรีใน sys.path


125

ฉันกำลังพยายามนำเข้าpycurl:

$ python -c "import pycurl"
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: libcurl.so.4: cannot open shared object file: No such file or directory

ตอนนี้libcurl.so.4อยู่ใน/usr/local/lib. อย่างที่คุณเห็นสิ่งนี้อยู่ในsys.path:

$ python -c "import sys; print(sys.path)"
['', '/usr/local/lib/python2.5/site-packages/setuptools-0.6c9-py2.5.egg', 
'/usr/local/lib/python25.zip', '/usr/local/lib/python2.5', 
'/usr/local/lib/python2.5/plat-linux2', '/usr/local/lib/python2.5/lib-tk', 
'/usr/local/lib/python2.5/lib-dynload', 
'/usr/local/lib/python2.5/sitepackages', '/usr/local/lib', 
'/usr/local/lib/python2.5/site-packages']

ความช่วยเหลือใด ๆ จะได้รับการชื่นชมอย่างมาก


ดูคำตอบที่อัปเดตของฉันในกรณีที่คุณตั้งค่าไม่LD_LIBRARY_PATHถูกต้อง (ฉันคิดว่าความคิดเห็นของคุณมีเครื่องหมายทวิภาคที่หายไป)
Vinay Sajip

1
มี symlink เสียชื่อ libcurl.so.4 หรือไม่ สำหรับฉันดูเหมือนว่ากำลังค้นหาไฟล์ แต่ไม่สามารถเปิดได้ หากทุกอย่างล้มเหลวให้รัดล่ามและมองหาสายที่ล้มเหลว
Charles Duffy

คำตอบ:


158

sys.pathจะค้นหาเฉพาะโมดูล Python LD_LIBRARY_PATHสำหรับห้องสมุดแบบไดนามิกที่เชื่อมโยงเส้นทางการสืบค้นจะต้องอยู่ใน ตรวจสอบว่าLD_LIBRARY_PATHรวมของคุณ/usr/local/libหรือไม่และหากไม่รวมให้เพิ่มแล้วลองอีกครั้ง

ข้อมูลเพิ่มเติม (ที่มา ):

ใน Linux ตัวแปรสภาพแวดล้อม LD_LIBRARY_PATH เป็นชุดไดเร็กทอรีที่คั่นด้วยโคลอนซึ่งควรค้นหาไลบรารีก่อนก่อนชุดไดเร็กทอรีมาตรฐาน สิ่งนี้มีประโยชน์เมื่อทำการดีบักไลบรารีใหม่หรือใช้ไลบรารีที่ไม่เป็นมาตรฐานเพื่อวัตถุประสงค์พิเศษ ตัวแปรสภาพแวดล้อม LD_PRELOAD แสดงรายการไลบรารีที่แบ่งใช้พร้อมฟังก์ชันที่แทนที่ชุดมาตรฐานเช่นเดียวกับที่ /etc/ld.so.preload ทำ สิ่งเหล่านี้ดำเนินการโดยตัวโหลด /lib/ld-linux.so ฉันควรทราบว่าในขณะที่ LD_LIBRARY_PATH ทำงานบนระบบที่คล้าย Unix หลายระบบ แต่ก็ใช้ไม่ได้กับทุกระบบ ตัวอย่างเช่นฟังก์ชันนี้พร้อมใช้งานบน HP-UX แต่เป็นตัวแปรสภาพแวดล้อม SHLIB_PATH และบน AIX ฟังก์ชันนี้ผ่านตัวแปร LIBPATH (ด้วยไวยากรณ์เดียวกันรายการที่คั่นด้วยโคลอน)

อัปเดต:ในการตั้งค่าLD_LIBRARY_PATHให้ใช้สิ่งใดสิ่งหนึ่งต่อไปนี้ตามความเหมาะสมใน~/.bashrc ไฟล์ของคุณหรือเทียบเท่า:

export LD_LIBRARY_PATH=/usr/local/lib

หรือ

export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH

ใช้รูปแบบแรกถ้าว่างเปล่า (เทียบเท่ากับสตริงว่างหรือไม่ปรากฏเลย) และรูปแบบที่สองถ้าไม่มี หมายเหตุการใช้งานของการส่งออก


2
ขอบคุณ ไม่ได้ตั้งค่า LD_LIBRARY_PATH ของฉันดังนั้น: $ LD_LIBRARY_PATH = / usr / local / lib $ LD_LIBRARY_PATH / usr / local / lib แต่ฉันยังคงได้รับข้อผิดพลาดเดิม: $ python -c "import pycurl" Traceback (การเรียกล่าสุดล่าสุด): ไฟล์ "<string>" บรรทัด 1 ใน <module> ImportError: libcurl.so.4: ไม่สามารถเปิดไฟล์อ็อบเจ็กต์ที่แชร์: ไม่มีไฟล์หรือไดเร็กทอรีดังกล่าว

2
ฉันต้องให้สิทธิ์แก่ผู้ใช้ในการอ่านไลบรารีหลังจากตั้งค่าตัวแปร LD_LIBRARY_PATH ในที่สุดก็ใช้งานได้
José Ricardo

57

ตรวจสอบให้แน่ใจว่าโมดูล libcurl.so ของคุณอยู่ในพา ธ ไลบรารีระบบซึ่งแตกต่างและแยกจากพา ธ ไลบรารี python

"การแก้ไขด่วน" คือการเพิ่มเส้นทางนี้ไปยังตัวแปร LD_LIBRARY_PATH อย่างไรก็ตามการตั้งค่าระบบนั้นให้กว้าง (หรือแม้แต่ทั้งบัญชี) เป็น BAD IDEA เนื่องจากเป็นไปได้ที่จะตั้งค่าในลักษณะที่บางโปรแกรมจะพบไลบรารีที่ไม่ควรหรือแย่กว่านั้นคือเปิดช่องโหว่ด้านความปลอดภัย

หาก "ไลบรารีที่ติดตั้งในเครื่อง" ของคุณติดตั้งอยู่ในตัวอย่างเช่น / usr / local / lib ให้เพิ่มไดเร็กทอรีนี้ไปที่ /etc/ld.so.conf (เป็นไฟล์ข้อความ) และเรียกใช้ "ldconfig"

คำสั่งจะเรียกใช้ยูทิลิตี้การแคช แต่จะสร้าง "ลิงก์สัญลักษณ์" ที่จำเป็นทั้งหมดที่จำเป็นสำหรับระบบโหลดเดอร์ในการทำงาน เป็นที่น่าแปลกใจที่ "ทำการติดตั้ง" สำหรับ libcurl ไม่ได้ทำสิ่งนี้แล้ว แต่เป็นไปได้ว่าจะทำไม่ได้ถ้า / usr / local / lib ไม่อยู่ใน /etc/ld.so.conf แล้ว

PS: เป็นไปได้ว่า /etc/ld.so.conf ของคุณไม่มีอะไรเลยนอกจาก "include ld.so.conf.d / *. conf" คุณยังคงสามารถเพิ่มพา ธ ไดเร็กทอรีหลังจากนั้นหรือเพียงแค่สร้างไฟล์ใหม่ภายในไดเร็กทอรีที่กำลังรวมอยู่ อย่าลืมเรียกใช้ "ldconfig" หลังจากนั้น

ระวัง. การทำผิดนี้อาจทำให้ระบบของคุณเสียหายได้

นอกจากนี้: ตรวจสอบให้แน่ใจว่าโมดูล python ของคุณคอมไพล์กับ libcurl เวอร์ชันนั้น หากคุณเพิ่งคัดลอกไฟล์บางไฟล์จากระบบอื่นสิ่งนี้จะไม่ได้ผลเสมอไป หากมีข้อสงสัยให้รวบรวมโมดูลของคุณในระบบที่คุณต้องการเรียกใช้


ขอบคุณ - สิ่งนี้ได้ผล ฉันสงสัยว่าเหตุใดฉันจึงพยายาม "แก้ไขด่วน" ก่อนหน้านี้เพื่อเปลี่ยนตัวแปร LD_LIBRARY_PATH

2
ขึ้นอยู่กับหลายปัจจัย นี่เป็นความเป็นไปได้อย่างหนึ่ง: โค้ดของคุณถูกเรียกใช้จาก apache หรือ cron โดยทั่วไปโปรแกรมเหล่านั้นจะ "ล้าง" สภาพแวดล้อมดังนั้นคุณต้องทำสิ่งต่างๆเพิ่มเติมเพื่อรับตัวแปรสภาพแวดล้อมเข้ามาตัวอย่างเช่น "SetEnv" ใน apache หรือการตั้งค่าตัวแปรในไฟล์ crontab สำหรับ cron โอกาสผิดพลาดไม่มีที่สิ้นสุด!
Ch'marr

24

คุณยังสามารถตั้งค่า LD_RUN_PATH เป็น / usr / local / lib ในสภาพแวดล้อมผู้ใช้ของคุณเมื่อคุณรวบรวม pycurl ตั้งแต่แรก สิ่งนี้จะฝัง / usr / local / lib ในแอตทริบิวต์ RPATH ของโมดูลส่วนขยาย C เพื่อให้ทราบโดยอัตโนมัติว่าจะหาไลบรารีที่ใดในขณะรันโดยไม่ต้องตั้งค่า LD_LIBRARY_PATH ในขณะรันไทม์


4
หรือใช้python setup.py build_ext --rpath=/usr/local/libเมื่อสร้างโมดูลส่วนขยายเพื่ออบในrpath
kynan

10

มีปัญหาเดียวกันแน่นอน ฉันติดตั้ง curl 7.19 เป็น / opt / curl / เพื่อให้แน่ใจว่าฉันจะไม่ส่งผลกระทบต่อ curl ปัจจุบันบนเซิร์ฟเวอร์การผลิตของเรา เมื่อฉันเชื่อมโยง libcurl.so.4 กับ / usr / lib:

sudo ln -s /opt/curl/lib/libcurl.so /usr/lib/libcurl.so.4

ฉันยังคงได้รับข้อผิดพลาดเดิม! Durf

แต่การเรียกใช้ ldconfig ทำให้การเชื่อมโยงสำหรับฉันและมันได้ผล ไม่จำเป็นต้องตั้งค่า LD_RUN_PATH หรือ LD_LIBRARY_PATH เลย จำเป็นแค่เรียกใช้ ldconfig


จะเกิดอะไรขึ้นถ้าฉันไม่มีสิทธิ์ sudo? ฉันไม่สามารถเรียกใช้ ldconfig ได้? มีวิธีใดในการล้างข้อผิดพลาดข้างต้นหรือไม่?
Prasanna

2
@SPRajagopal: หากคุณไม่มีสิทธิ์ในการแก้ไขแอตทริบิวต์ของระบบคุณต้องใช้LD_LIBRARY_PATHวิธีการตัวแปรสภาพแวดล้อมที่อธิบายไว้ข้างต้น หากคุณไม่ต้องการตั้งค่าใน~/.bashrc(การเพิ่มการตั้งค่านั้นไม่ใช่ความคิดที่ดี IMO) คุณสามารถเขียนเชลล์สคริปต์ที่ตั้งค่าตัวแปรนี้จากนั้นเรียกใช้ python จากนั้นเรียกใช้สคริปต์นั้น
MadScientist

8

ในฐานะที่เป็นส่วนเสริมของคำตอบข้างต้น - ฉันเพิ่งพบปัญหาที่คล้ายกันและทำงานได้อย่างสมบูรณ์กับ python ที่ติดตั้งเริ่มต้น

เมื่อฉันเรียกตัวอย่างของไลบรารีวัตถุที่ใช้ร่วมกันที่ฉันกำลังมองหาLD_LIBRARY_PATHฉันจะได้รับสิ่งนี้:

$ LD_LIBRARY_PATH=/path/to/mysodir:$LD_LIBRARY_PATH python example-so-user.py
python: can't open file 'example-so-user.py': [Errno 2] No such file or directory

โดยเฉพาะอย่างยิ่งมันไม่ได้บ่นเกี่ยวกับการนำเข้า - มันบ่นเกี่ยวกับไฟล์ต้นฉบับ!

แต่ถ้าฉันบังคับให้โหลดวัตถุโดยใช้LD_PRELOAD:

$ LD_PRELOAD=/path/to/mysodir/mypyobj.so python example-so-user.py
python: error while loading shared libraries: libtiff.so.5: cannot open shared object file: No such file or directory

... ฉันได้รับข้อความแสดงข้อผิดพลาดที่มีความหมายมากขึ้นทันที - เกี่ยวกับการพึ่งพาที่ขาดหายไป!

แค่คิดว่าฉันจะจดไว้ที่นี่ - ไชโย!


แน่ใจหรือว่าไม่ใช่ข้อผิดพลาดใหม่ที่เกิดขึ้นก่อนข้อผิดพลาดของ OP
David Knipe

1

ฉันใช้python setup.py build_ext -R/usr/local/lib -I/usr/local/include/libcalg-1.0และไฟล์. so ที่คอมไพล์แล้วอยู่ภายใต้โฟลเดอร์ build คุณสามารถพิมพ์python setup.py --help build_extเพื่อดูคำอธิบายของ -R และ -I


1

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

ฉันมีข้อผิดพลาดเดียวกันนี้หลังจากการอัปเดตระบบปฏิบัติการ แต่ได้รับการแก้ไขอย่างง่ายดายด้วยpyenv install 3.7-dev(เวอร์ชันที่ฉันใช้)

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