ฉันจำเป็นต้องรู้ว่ามีโมดูลหลามอยู่หรือไม่โดยไม่ต้องนำเข้า
การนำเข้าสิ่งที่อาจไม่มีอยู่ (ไม่ใช่สิ่งที่ฉันต้องการ):
try:
import eggs
except ImportError:
pass
ฉันจำเป็นต้องรู้ว่ามีโมดูลหลามอยู่หรือไม่โดยไม่ต้องนำเข้า
การนำเข้าสิ่งที่อาจไม่มีอยู่ (ไม่ใช่สิ่งที่ฉันต้องการ):
try:
import eggs
except ImportError:
pass
คำตอบ:
เพื่อตรวจสอบว่าการนำเข้าสามารถค้นหาบางสิ่งใน python2 โดยใช้ imp
import imp
try:
imp.find_module('eggs')
found = True
except ImportError:
found = False
ในการค้นหาการนำเข้าประคุณต้องทำสิ่งต่อไปนี้:
import imp
try:
spam_info = imp.find_module('spam')
spam = imp.load_module('spam', *spam_info)
imp.find_module('eggs', spam.__path__) # __path__ is already a list
found = True
except ImportError:
found = False
นอกจากนี้คุณยังสามารถใช้pkgutil.find_loader
(มากขึ้นหรือน้อยลงเช่นเดียวกับส่วน python3
import pkgutil
eggs_loader = pkgutil.find_loader('eggs')
found = eggs_loader is not None
คุณควรใช้importlib
วิธีที่ฉันทำเกี่ยวกับการทำเช่นนี้คือ:
import importlib
spam_loader = importlib.find_loader('spam')
found = spam_loader is not None
ความคาดหวังของฉันคือถ้าคุณสามารถหาตัวโหลดได้มันก็มีอยู่ นอกจากนี้คุณยังฉลาดกว่านี้อีกเล็กน้อยเช่นกรองตัวตักที่คุณจะยอมรับ ตัวอย่างเช่น:
import importlib
spam_loader = importlib.find_loader('spam')
# only accept it as valid if there is a source file for the module - no bytecode only.
found = issubclass(type(spam_loader), importlib.machinery.SourceFileLoader)
ใน Python3.4 importlib.find_loader
เอกสารหลามimportlib.util.find_spec
ได้รับการยกเลิกในความโปรดปรานของ importlib.util.find_spec
วิธีที่แนะนำคือ มีคนอื่นที่ชอบimportlib.machinery.FileFinder
ซึ่งมีประโยชน์ถ้าคุณหลังจากโหลดไฟล์เฉพาะ การหาวิธีใช้มันเกินขอบเขตของสิ่งนี้
import importlib
spam_spec = importlib.util.find_spec("spam")
found = spam_spec is not None
วิธีนี้ใช้ได้กับการนำเข้าแบบสัมพัทธ์ แต่คุณต้องระบุแพ็คเกจเริ่มต้นดังนั้นคุณสามารถทำได้:
import importlib
spam_spec = importlib.util.find_spec("..spam", package="eggs.bar")
found = spam_spec is not None
spam_spec.name == "eggs.spam"
ในขณะที่ฉันแน่ใจว่ามีเหตุผลในการทำเช่นนี้ - ฉันไม่แน่ใจว่ามันจะเป็นอะไร
เมื่อพยายามหา submodule มันจะนำเข้าโมดูลหลัก (สำหรับวิธีการทั้งหมดข้างต้น)!
food/
|- __init__.py
|- eggs.py
## __init__.py
print("module food loaded")
## eggs.py
print("module eggs")
were you then to run
>>> import importlib
>>> spam_spec = importlib.find_spec("food.eggs")
module food loaded
ModuleSpec(name='food.eggs', loader=<_frozen_importlib.SourceFileLoader object at 0x10221df28>, origin='/home/user/food/eggs.py')
ยินดีต้อนรับความคิดเห็นเกี่ยวกับการเดินทางรอบนี้
find_loader
eggs.ham.spam
นี้จะทำงานเฉพาะสำหรับโมดูลระดับบนสุดไม่ได้สำหรับ
spam
ในeggs.ham
ที่คุณจะใช้imp.find_module('spam', ['eggs', 'ham'])
pkgutil.find_loader("my.package.module")
คืนค่าตัวโหลดหากแพ็กเกจ / โมดูลอยู่และNone
ถ้าไม่ โปรดอัปเดตคำตอบของคุณสำหรับ Python 2 เนื่องจากการปิดบัง ImportError ทำให้ฉันเป็นบ้าเมื่อวานนี้ xP
หลังจากที่การตอบสนองการใช้งาน yarbelk ìmp
ของผมได้ทำนี้ไม่จำเป็นต้องนำเข้า
try:
__import__('imp').find_module('eggs')
# Make things with supposed existing module
except ImportError:
pass
มีประโยชน์ในsettings.py
ตัวอย่างของ Django
ModuleNotFoundError
ได้รับการแนะนำในหลาม 3.6และสามารถนำมาใช้เพื่อการนี้
try:
import eggs
except ModuleNotFoundError:
# Error handling
pass
เกิดข้อผิดพลาดขึ้นเมื่อไม่พบโมดูลหรือหนึ่งในพาเรนต์ ดังนั้น
try:
import eggs.sub
except ModuleNotFoundError as err:
# Error handling
print(err)
จะพิมพ์ข้อความที่ดูเหมือนNo module named 'eggs'
ว่าeggs
ไม่พบโมดูล; แต่จะพิมพ์บางอย่างเช่นNo module named 'eggs.sub'
หากsub
ไม่พบโมดูลเท่านั้น แต่สามารถค้นหาeggs
แพ็คเกจได้
ดูเอกสารประกอบของระบบนำเข้าสำหรับข้อมูลเพิ่มเติมเกี่ยวกับModuleNotFoundError
จนกว่าจะมีการอัปเดตคำตอบปัจจุบันต่อไปนี้เป็นวิธีสำหรับPython 2
import pkgutil
import importlib
if pkgutil.find_loader(mod) is not None:
return importlib.import_module(mod)
return None
คำตอบจำนวนมากใช้ประโยชน์จากการจับImportError
และ ปัญหาที่เกิดขึ้นคือเราไม่สามารถรู้ได้ว่าสิ่งใดที่ทำให้เกิดปัญหาImportError
ปัญหา
ถ้าคุณนำเข้าของคุณexistantโมดูลและมีเกิดขึ้นเป็นImportError
ในโมดูลของคุณ (เช่นพิมพ์ผิดในบรรทัด 1) ผลที่ได้จะเป็นไปได้ว่าโมดูลของคุณไม่อยู่ มันจะทำให้คุณมีจำนวน backtracking ค่อนข้างมากที่จะคิดว่าโมดูลของคุณมีอยู่และImportError
ถูกจับและทำให้สิ่งต่าง ๆ ล้มเหลวอย่างเงียบ ๆ
ImportError
- โปรดแก้ไขหากไม่ชัดเจนสำหรับคุณ
คำตอบของ go_as ในฐานะหนึ่งซับ
python -c "help('modules');" | grep module
ฉันเจอคำถามนี้ในขณะที่ค้นหาวิธีการตรวจสอบว่ามีการโหลดโมดูลจากบรรทัดคำสั่งหรือไม่ และต้องการแบ่งปันความคิดของฉันสำหรับสิ่งที่ตามมาและมองหาสิ่งเดียวกัน:
วิธีไฟล์สคริปต์ Linux / UNIX : สร้างไฟล์module_help.py
:
#!/usr/bin/env python
help('modules')
จากนั้นตรวจสอบให้แน่ใจว่าปฏิบัติการได้: chmod u+x module_help.py
และเรียกมันด้วย a pipe
ถึงgrep
:
./module_help.py | grep module_name
เรียกใช้ระบบช่วยเหลือในตัว (ฟังก์ชั่นนี้มีไว้สำหรับการใช้งานแบบอินเทอร์แอคทีฟ ) หากไม่มีการระบุอาร์กิวเมนต์ระบบวิธีใช้แบบโต้ตอบจะเริ่มต้นที่คอนโซลของล่าม หากอาร์กิวเมนต์เป็นสตริงสตริงนั้นจะถูกค้นหาเป็นชื่อของโมดูลฟังก์ชันคลาสเมธอดคำสำคัญหรือเอกสารคู่มือและหน้าวิธีใช้ถูกพิมพ์บนคอนโซล หากอาร์กิวเมนต์เป็นวัตถุชนิดอื่นหน้าความช่วยเหลือบนวัตถุจะถูกสร้างขึ้น
วิธีการโต้ตอบ : ในการโหลดคอนโซลpython
>>> help('module_name')
หากพบว่าเลิกอ่านโดยพิมพ์q
เพื่อออกจากเซสชันการโต้ตอบของหลามกดCtrl+D
วิธีการไฟล์สคริปต์ Windowsยังรองรับ Linux / UNIX และโดยรวมดีขึ้น :
#!/usr/bin/env python
import sys
help(sys.argv[1])
เรียกมันจากคำสั่งเช่น:
python module_help.py site
จะส่งออก:
ช่วยในเว็บไซต์โมดูล:
NAME
site - ผนวกพา ธ การค้นหาโมดูลสำหรับแพ็คเกจบุคคลที่สามไปยัง sys.path
FILE
/usr/lib/python2.7/site.py
MODULE DOCS
http://docs.python.org/library/site
DESCRIPTION
...
:
และคุณต้องกดq
เพื่อออกจากโหมดโต้ตอบ
ใช้มันโมดูลที่ไม่รู้จัก:
python module_help.py lkajshdflkahsodf
จะส่งออก:
ไม่พบเอกสาร Python สำหรับ 'lkajshdflkahsodf'
และออกจาก
ใช้หนึ่งในฟังก์ชั่นจาก pkgutilตัวอย่างเช่น:
from pkgutil import iter_modules
def module_exists(module_name):
return module_name in (name for loader, name, ispkg in iter_modules())
ง่ายกว่าถ้าคำสั่งจาก AskUbuntu: ฉันจะตรวจสอบว่าโมดูลได้รับการติดตั้งใน Python ได้อย่างไร?
import sys
print('eggs' in sys.modules)
คุณสามารถเขียนสคริปต์เล็กน้อยที่จะพยายามนำเข้าโมดูลทั้งหมดและบอกคุณว่าโมดูลใดทำงานล้มเหลวและโมดูลใดทำงานได้:
import pip
if __name__ == '__main__':
for package in pip.get_installed_distributions():
pack_string = str(package).split(" ")[0]
try:
if __import__(pack_string.lower()):
print(pack_string + " loaded successfully")
except Exception as e:
print(pack_string + " failed with error code: {}".format(e))
เอาท์พุท:
zope.interface loaded successfully
zope.deprecation loaded successfully
yarg loaded successfully
xlrd loaded successfully
WMI loaded successfully
Werkzeug loaded successfully
WebOb loaded successfully
virtualenv loaded successfully
...
คำเตือนนี้จะพยายามนำเข้าทุกอย่างดังนั้นคุณจะเห็นสิ่งต่าง ๆ เช่นPyYAML failed with error code: No module named pyyaml
เนื่องจากชื่อการนำเข้าที่แท้จริงเป็นเพียง yaml ดังนั้นตราบใดที่คุณรู้การนำเข้าของคุณสิ่งนี้ควรทำเพื่อคุณ
ฉันเขียนฟังก์ชันผู้ช่วยนี้:
def is_module_available(module_name):
if sys.version_info < (3, 0):
# python 2
import importlib
torch_loader = importlib.find_loader(module_name)
elif sys.version_info <= (3, 3):
# python 3.0 to 3.3
import pkgutil
torch_loader = pkgutil.find_loader(module_name)
elif sys.version_info >= (3, 4):
# python 3.4 and above
import importlib
torch_loader = importlib.util.find_spec(module_name)
return torch_loader is not None
คุณยังสามารถใช้importlib
โดยตรง
import importlib
try:
importlib.import_module(module_name)
except ImportError:
# Handle error
ไม่มีวิธีที่จะตรวจสอบได้อย่างน่าเชื่อถือว่า "โมดูลจุด" สามารถนำเข้าได้โดยไม่ต้องนำเข้าแพ็คเกจหลัก การพูดแบบนี้มีวิธีแก้ไขปัญหามากมาย "วิธีตรวจสอบว่ามีโมดูล Python อยู่หรือไม่"
ด้านล่างวิธีการแก้ไขปัญหาที่โมดูลที่นำเข้าสามารถยก ImportError แม้มันจะมีอยู่ เราต้องการแยกแยะสถานการณ์นั้นจากสิ่งที่ไม่มีอยู่ในโมดูล
Python 2 :
import importlib
import pkgutil
import sys
def find_module(full_module_name):
"""
Returns module object if module `full_module_name` can be imported.
Returns None if module does not exist.
Exception is raised if (existing) module raises exception during its import.
"""
module = sys.modules.get(full_module_name)
if module is None:
module_path_tail = full_module_name.split('.')
module_path_head = []
loader = True
while module_path_tail and loader:
module_path_head.append(module_path_tail.pop(0))
module_name = ".".join(module_path_head)
loader = bool(pkgutil.find_loader(module_name))
if not loader:
# Double check if module realy does not exist
# (case: full_module_name == 'paste.deploy')
try:
importlib.import_module(module_name)
except ImportError:
pass
else:
loader = True
if loader:
module = importlib.import_module(full_module_name)
return module
Python 3 :
import importlib
def find_module(full_module_name):
"""
Returns module object if module `full_module_name` can be imported.
Returns None if module does not exist.
Exception is raised if (existing) module raises exception during its import.
"""
try:
return importlib.import_module(full_module_name)
except ImportError as exc:
if not (full_module_name + '.').startswith(exc.name + '.'):
raise
ใน django.utils.module_loading.module_has_submodule
import sys
import os
import imp
def module_has_submodule(package, module_name):
"""
check module in package
django.utils.module_loading.module_has_submodule
"""
name = ".".join([package.__name__, module_name])
try:
# None indicates a cached miss; see mark_miss() in Python/import.c.
return sys.modules[name] is not None
except KeyError:
pass
try:
package_path = package.__path__ # No __path__, then not a package.
except AttributeError:
# Since the remainder of this function assumes that we're dealing with
# a package (module with a __path__), so if it's not, then bail here.
return False
for finder in sys.meta_path:
if finder.find_module(name, package_path):
return True
for entry in package_path:
try:
# Try the cached finder.
finder = sys.path_importer_cache[entry]
if finder is None:
# Implicit import machinery should be used.
try:
file_, _, _ = imp.find_module(module_name, [entry])
if file_:
file_.close()
return True
except ImportError:
continue
# Else see if the finder knows of a loader.
elif finder.find_module(name):
return True
else:
continue
except KeyError:
# No cached finder, so try and make one.
for hook in sys.path_hooks:
try:
finder = hook(entry)
# XXX Could cache in sys.path_importer_cache
if finder.find_module(name):
return True
else:
# Once a finder is found, stop the search.
break
except ImportError:
# Continue the search for a finder.
continue
else:
# No finder found.
# Try the implicit import machinery if searching a directory.
if os.path.isdir(entry):
try:
file_, _, _ = imp.find_module(module_name, [entry])
if file_:
file_.close()
return True
except ImportError:
pass
# XXX Could insert None or NullImporter
else:
# Exhausted the search, so the module cannot be found.
return False