如何检查模块/库/包是否是 python 标准库的一部分?

2022-01-13 00:00:00 python module package native

问题描述

我已经用 pip 安装了很多库/模块/包,现在我无法区分哪些是 Python 标准库的原生库,哪些不是.当我的代码在我的机器上运行但在其他任何地方都不起作用时,这会导致问题.

I have installed sooo many libraries/modules/packages with pip and now I cannot differentiate which is native to the python standard library and which is not. This causes problem when my code works on my machine but it doesn't work anywhere else.

如何检查我在代码中导入的模块/库/包是否来自 python stdlib?

假设检查是在具有所有外部库/模块/包的机器上完成的,否则我可以简单地在没有它们的另一台机器上执行 try-except 导入.

Assume that the checking is done on the machine with all the external libraries/modules/packages, otherwise I could simply do a try-except import on the other machine that doesn't have them.

例如,我确信这些导入可以在我的机器上运行,但是当它在仅安装了普通 Python 的机器上时,它会中断:

For example, I am sure these imports work on my machine, but when it's on a machine with only a plain Python install, it breaks:

from bs4 import BeautifulSoup
import nltk
import PIL
import gensim


解决方案

您必须检查所有已导入的模块,看看其中是否有任何模块位于标准库之外.

You'd have to check all modules that have been imported to see if any of these are located outside of the standard library.

以下脚本不是防弹的,但应该为您提供一个起点:

The following script is not bulletproof but should give you a starting point:

import sys
import os

external = set()
exempt = set()
paths = (os.path.abspath(p) for p in sys.path)
stdlib = {p for p in paths
          if p.startswith((sys.prefix, sys.real_prefix)) 
          and 'site-packages' not in p}
for name, module in sorted(sys.modules.items()):
    if not module or name in sys.builtin_module_names or not hasattr(module, '__file__'):
        # an import sentinel, built-in module or not a real module, really
        exempt.add(name)
        continue

    fname = module.__file__
    if fname.endswith(('__init__.py', '__init__.pyc', '__init__.pyo')):
        fname = os.path.dirname(fname)

    if os.path.dirname(fname) in stdlib:
        # stdlib path, skip
        exempt.add(name)
        continue

    parts = name.split('.')
    for i, part in enumerate(parts):
        partial = '.'.join(parts[:i] + [part])
        if partial in external or partial in exempt:
            # already listed or exempted
            break
        if partial in sys.modules and sys.modules[partial]:
            # just list the parent name and be done with it
            external.add(partial)
            break

for name in external:
    print name, sys.modules[name].__file__

这是一个新模块,在脚本中的所有导入之后导入它,它会打印它认为不是标准库一部分的所有模块.

Put this is a new module, import it after all imports in your script, and it'll print all modules that it thinks are not part of the standard library.

相关文章