如何在不导入模块的情况下知道Python模块是否存在?
导入可能不存在的内容(不是我想要的)会导致:
try:
import eggs
except ImportError:
pass
如何在不导入模块的情况下知道Python模块是否存在?
导入可能不存在的内容(不是我想要的)会导致:
try:
import eggs
except ImportError:
pass
简短概述) 使用 importlib.util.find_spec(module_name)
(Python 3.4+)。
imp.find_module
为了检查在Python 2中是否可以找到某个东西,使用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
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)
importlib.util.find_spec
在Python 3.4中,importlib.find_loader
Python documentation已被弃用,推荐使用importlib.util.find_spec
。建议使用importlib.util.find_spec
方法。还有其他方法,如importlib.machinery.FileFinder
,如果您需要加载特定文件,则非常有用。但是,如何使用它们超出了本文的范围。
import importlib.util
spam_spec = importlib.util.find_spec("spam")
found = spam_spec is not None
这也适用于相对导入,但您必须提供起始包,因此您也可以这样做:
import importlib.util
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')
欢迎评论如何解决这个问题
find_loader
eggs.ham.spam
。 - hemfliteggs.ham
中查找 spam
,您需要使用imp.find_module('spam', ['eggs', 'ham'])
。 - gitaarikimp
被废弃,推荐使用importlib
代替。+1。 - rvighne在Python 3.6中引入了ModuleNotFoundError
,可用于此目的:
try:
import eggs
except ModuleNotFoundError:
# Error handling
pass
当无法找到一个模块或其父模块时,就会引发该错误。
try:
import eggs.sub
except ModuleNotFoundError as err:
# Error handling
print(err)
如果找不到eggs
模块,它将打印类似于No module named 'eggs'
的消息;但是,如果只有sub
模块找不到,但可以找到eggs
包,则会打印类似于No module named 'eggs.sub'
的消息。
有关ModuleNotFoundError
的更多信息,请参见导入系统文档。
在更新当前答案之前,这是适用于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
被捕获并使事情悄无声息地失败了。
使用yarbelk的回答后,我做了这个,所以不必导入imp
。
try:
__import__('imp').find_module('eggs')
# Make things with a supposed existing module
except ImportError:
pass
例如,在 Django 的 settings.py 文件中非常有用。
以下是检查模块是否从命令行加载的方法:
Linux/UNIX 脚本文件方法:创建一个名为module_help.py
的文件:
#!/usr/bin/env python
help('modules')
然后确保它是可执行的:chmod u+x module_help.py
并使用管道
调用它到grep
:
./module_help.py | grep module_name
python
。>>> help('module_name')
如果找到了,输入q
退出阅读。
要退出Python解释器交互会话,请按Ctrl+D。
Windows脚本文件方法,也适用于Linux/UNIX,并且整体效果更好:
#!/usr/bin/env python
import sys
help(sys.argv[1])
从命令行中调用:
python module_help.py site
会输出:
模块 site 的帮助信息:
名称
site - 将第三方包的模块搜索路径添加到 sys.path。
文件
/usr/lib/python2.7/site.py
模块文档
http://docs.python.org/library/site
描述
...
您需要按下 q
退出交互模式。
对于未知的模块,例如:
python module_help.py lkajshdflkahsodf
将输出:
'lkajshdflkahsodf' 的 Python 文档未找到
并退出。
使用pkgutil中的一个函数,例如:
pkgutil.iter_modulesfrom pkgutil import iter_modules
def module_exists(module_name):
return module_name in (name for loader, name, ispkg in iter_modules())
我写了这个帮助函数:
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
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。所以只要你知道你的导入,这应该对你有帮助。
你也可以直接使用 importlib.util
import importlib.util
def module_exists_without_import(module_name):
spec = importlib.util.find_spec(module_name)
return spec is not None