我如何知道Python模块是否存在,而不导入它?
导入一些可能不存在(不是我想要的)的东西会导致:
try:
import eggs
except ImportError:
pass
我如何知道Python模块是否存在,而不导入它?
导入一些可能不存在(不是我想要的)的东西会导致:
try:
import eggs
except ImportError:
pass
当前回答
你可以写一个小脚本,尝试导入所有的模块,并告诉你哪些是失败的,哪些是工作的:
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失败的错误代码:没有名为PyYAML的模块,因为实际的导入名称只是yaml。只要知道导入,这个就能帮到你。
其他回答
Python 2,不依赖于ImportError
在当前答案更新之前,以下是Python 2的方法
import pkgutil
import importlib
if pkgutil.find_loader(mod) is not None:
return importlib.import_module(mod)
return None
为什么又是另一个答案?
很多答案都利用了捕捉ImportError。问题是,我们不知道是什么引发了ImportError。
如果你导入了你现有的模块,而你的模块中恰好有一个ImportError(例如,第1行有错字),结果将是你的模块不存在。
这将花费您大量的回溯来确定您的模块是否存在,ImportError被捕获并使事情无声地失败。
使用importlib.util.find_spec(module_name) (Python 3.4+)。
Python2: imp.find_module
要检查import是否能在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(与Python 3部分大致相同:
import pkgutil
eggs_loader = pkgutil.find_loader('eggs')
found = eggs_loader is not None
Python 3
Python 3≤3.3:importlib.find_loader
你应该使用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)
Python 3≥3.4:importlib.util.find_spec
在Python 3.4中importlib。Python文档已弃用,取而代之的是importlib.util.find_spec。推荐使用importlib.util.find_spec方法。还有其他的,比如进口机械。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"
虽然我确信这样做是有原因的,但我不确定是什么原因。
警告
当试图找到子模块时,它将导入父模块(对于上述所有方法)!
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.util.find_spec("food.eggs")
module food loaded
ModuleSpec(name='food.eggs', loader=<_frozen_importlib.SourceFileLoader object at 0x10221df28>, origin='/home/user/food/eggs.py')
欢迎就如何解决这个问题发表评论
确认
@rvighne for importlib @lucas-guido for Python 3.3+弃用find_loader @enpenax for pkgutils。Python 2.7中的find_loader行为
Ask Ubuntu的一个更简单的if语句,如何检查Python中是否安装了一个模块?:
import sys
print('eggs' in sys.modules)
你也可以使用importlib。util直接
import importlib.util
def module_exists_without_import(module_name):
spec = importlib.util.find_spec(module_name)
return spec is not None
如果你知道文件的位置,想要检查相应的Python代码文件是否有该模块,你可以简单地通过Python中的astor包进行检查。这里有一个简单的例子:
"""
Check if a module function exists or not without importing a Python package file
"""
import ast
import astor
tree = astor.parse_file('handler.py')
method_to_check = 'handle'
for item in tree.body:
if isinstance(item, ast.FunctionDef):
if item.name == method_to_check:
print('method exists')
break