วิธีตรวจสอบว่ามีการนำเข้าโมดูล python หรือไม่?


93

ฉันจะตรวจสอบได้อย่างไรว่าฉันนำเข้าโมดูลที่ใดที่หนึ่งในโค้ด

 if not has_imported("somemodule"):
     print('you have not imported somemodule')

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


เพียงใส่raise SystemError()(หรือข้อยกเว้นอื่น ๆ ที่คุณเลือก) ที่ด้านบนของโมดูลที่คุณไม่ต้องการนำเข้า หากคุณไม่จริงนำเข้ามันบางโปรแกรมของคุณจะโยน traceback และออก
larsks

การนำเข้าโมดูลจะทำให้โปรแกรมของคุณยุ่งเหยิงได้อย่างไร? ฟังดูไม่น่าจะเป็นไปได้
Bill Woodger

1
@BillWoodger: บางทีที่โมดูลเปลี่ยนสถานะระดับโลกที่คุณไม่ต้องการเปลี่ยนแปลง
Martijn Pieters

@MartijnPieters Yoiks. และนำเข้าเสียงให้เป็นกลาง
Bill Woodger

คำตอบ:


126

ทดสอบชื่อโมดูลในsys.modulesพจนานุกรม :

import sys

modulename = 'datetime'
if modulename not in sys.modules:
    print 'You have not imported the {} module'.format(modulename)

จากเอกสาร:

นี่คือพจนานุกรมที่แมปชื่อโมดูลกับโมดูลที่โหลดไปแล้ว

สังเกตว่าimportคำสั่งทำสองสิ่ง:

  1. ถ้าโมดูลไม่เคยได้รับก่อนที่จะนำเข้า (== ในไม่อยู่sys.modules) sys.modulesจากนั้นจะมีการโหลดและเพิ่มไปยัง
  2. ผูกชื่อ 1 ชื่อขึ้นไปในเนมสเปซปัจจุบันที่อ้างอิงอ็อบเจ็กต์โมดูลหรืออ็อบเจ็กต์ที่เป็นสมาชิกของเนมสเปซโมดูล

นิพจน์จะmodulename not in sys.modulesทดสอบว่าขั้นตอนที่ 1 เกิดขึ้นหรือไม่ การทดสอบผลลัพธ์ของขั้นตอนที่ 2 ต้องการให้ทราบว่าimportคำสั่งที่แน่นอนถูกใช้เนื่องจากตั้งชื่อที่แตกต่างกันเพื่ออ้างอิงวัตถุต่างกัน

  • import modulename ชุด modulename = sys.modules['modulename']
  • import packagename.nestedmoduleชุดpackagename = sys.modules['packagename'](ไม่ว่าคุณจะเพิ่มระดับเพิ่มเติมกี่ระดับก็ตาม)
  • import modulename as altname ชุด altname = sys.module['modulename']
  • import packagename.nestedmodule as altname ชุด altname = sys.modules['packagename.nestedmodule']
  • from somemodule import objectname ชุด objectname = sys.modules['somemodule'].objectname
  • from packagename import nestedmodulenameชุดnestedmodulename = sys.modules['packagename.nestedmodulename'](เฉพาะเมื่อไม่มีวัตถุที่ตั้งชื่อnestedmodulenameในpackagenameเนมสเปซก่อนการนำเข้านี้ชื่อเพิ่มเติมสำหรับโมดูลที่ซ้อนกันจะถูกเพิ่มในเนมสเปซแพ็กเกจหลัก ณ จุดนี้)
  • from somemodule import objectname as altname ชุด altname = sys.modules['somemodule'].objectname
  • from packagename import nestedmodulename as altnameชุดaltname = sys.modules['packagename.nestedmodulename'](เฉพาะเมื่อไม่มีวัตถุที่ตั้งชื่อnestedmodulenameในpackagenameเนมสเปซก่อนการนำเข้านี้ชื่อเพิ่มเติมสำหรับโมดูลที่ซ้อนกันจะถูกเพิ่มในเนมสเปซแพ็กเกจหลัก ณ จุดนี้)

คุณสามารถทดสอบว่าชื่อที่ถูกผูกไว้กับวัตถุที่นำเข้ามีอยู่ในเนมสเปซที่กำหนดหรือไม่:

# is this name visible in the current scope:
'importedname' in dir()

# or, is this a name in the globals of the current module:
'importedname' in globals()

# or, does the name exist in the namespace of another module:
'importedname' in globals(sys.modules['somemodule'])

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


1
นี่เป็นวิธีที่ดีที่สุดในการตรวจสอบแพ็กเกจที่ต้องการภายในฟังก์ชันหรือไม่ กล่าวคือบางฟังก์ชันต้องใช้numpyแพ็กเกจ - การใช้งานimport sysภายในฟังก์ชันนั้นดีที่สุดในการตรวจสอบว่ามีการนำเข้าหรือไม่ โดย "ดีที่สุด" ฉันหมายถึงในแง่ของผลกระทบด้านประสิทธิภาพตามที่import sysจะเรียกทุกครั้งที่เรียกใช้ฟังก์ชัน ขอบคุณ
สับสน

@ พบว่าคุณสามารถนำเข้า sys ภายนอกฟังก์ชันได้หากทำให้คุณกังวล ไม่ใช่ว่าimport sysแพง แต่อย่างใด sysมีอยู่เสมอโดยค่าเริ่มต้นโหลดแล้ว แต่สำหรับแพคเกจตัวเลือก: เพียงแค่นำเข้าแพคเกจ ตรวจจับImportErrorข้อยกเว้นหากไม่ได้ติดตั้งแพ็กเกจและตั้งค่าสถานะที่ระบุว่าติดตั้งเมื่อการนำเข้าสำเร็จ หลังจากนั้นคุณสามารถใช้แฟล็กเพื่อแจ้งการใช้การอ้างอิงที่เป็นทางเลือก
Martijn Pieters

@Confounded การname in sys.modulesทดสอบจะมีประโยชน์หากคุณไม่ต้องการนำเข้าเท่านั้น
Martijn Pieters

26

สำหรับคำตอบ sys.modules ที่ยอมรับฉันจะเพิ่มข้อแม้หนึ่งข้อเพื่อระวังเกี่ยวกับการเปลี่ยนชื่อโมดูลเมื่อนำเข้า:

>>> import sys
>>> import datetime as dt
>>> 'dt' in sys.modules
False
>>> 'datetime' in sys.modules
True

18

ใช้ sys.modules เพื่อทดสอบว่ามีการนำเข้าโมดูลหรือไม่ (ฉันใช้ unicodedata เป็นตัวอย่าง):

>>> import sys
>>> 'unicodedata' in sys.modules
False
>>> import unicodedata
>>> 'unicodedata' in sys.modules
True

5

sys.modules มีโมดูลทั้งหมดที่ใช้ที่ใดก็ได้ในอินสแตนซ์ปัจจุบันของล่ามและจะปรากฏขึ้นหากนำเข้าในโมดูล Python อื่น ๆ

dir() ตรวจสอบว่าชื่อถูกกำหนดในเนมสเปซปัจจุบันหรือไม่

การรวมกันของทั้ง 2 นั้นปลอดภัยกว่าการแยกกันและใช้ได้ผลตราบเท่าที่คุณไม่ได้กำหนดcopyตัวเอง

if ('copy' in sys.modules) and ('copy' in dir()):

0
if "sys" not in dir():
  print("sys not imported!")

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