如何确定模块名称是否是Python标准库的一部分

问题描述 投票:0回答:5

我有一个模块名称作为字符串(例如“日志记录”),它是通过查询对象的module属性给出的。

如何区分属于我的项目的模块和属于 python 标准库的模块?

我知道我可以使用 pip.get_installed_distributions() 检查这个模块是否是由 pip 安装的,但这些与标准库无关

注意:我正在研究 python 2.7,因此仅在 python 3.x 中有效的解决方案不太相关。

here的答案不同,我正在寻找一种可以在 O(1) 中运行的解决方案,并且不需要保存结果数组,也不需要扫描每个查询的目录。

谢谢。

python python-2.7
5个回答
5
投票

编辑:

我使用了这个解决方案(来源)。

import distutils.sysconfig as sysconfig
import os

def std_modules():
    ret_list = []
    std_lib = sysconfig.get_python_lib(standard_lib=True)
    for top, dirs, files in os.walk(std_lib):
        for nm in files:
            if nm != '__init__.py' and nm[-3:] == '.py':
                ret_list.append(os.path.join(top, nm)[len(std_lib)+1:-3].replace('\\','.'))
    return ret_list
            
l = std_modules()
print("logging" in l)
print("os" in l)

输出:

False
True

这适用于 Python 2 和 Python 3。

编辑前:

我想,你可以使用Python Docs。以下是 Python 2 DocsPython 3 Docs 的标准库部分。此外,您还可以选择准确的 Python 版本。


4
投票

快速但肮脏的解决方案,使用标准模块imp

import imp
import os.path
import sys

python_path = os.path.dirname(sys.executable)

my_mod_name = 'logging'

module_path = imp.find_module(my_mod_name)[1]
if 'site-packages' in module_path or python_path in module_path or not imp.is_builtin(my_mod_name):
    print('module', my_mod_name, 'is not included in standard python library')

2
投票

上面的解决方案都不是我想要的,所以我又用了另一种方法。发布在这里以防对任何人有用。

import os

def standard_lib_names_gen(include_underscored=False):
    standard_lib_dir = os.path.dirname(os.__file__)
    for filename in os.listdir(standard_lib_dir):
        if not include_underscored and filename.startswith('_'):
            continue
        filepath = os.path.join(standard_lib_dir, filename)
        name, ext = os.path.splitext(filename)
        if filename.endswith('.py') and os.path.isfile(filepath):
            if str.isidentifier(name):
                yield name
        elif os.path.isdir(filepath) and '__init__.py' in os.listdir(filepath):
            yield name
>>> standard_lib_names = set(standard_lib_names_gen(include_underscored=True))
>>> # verify that a few known libs are there (including three folders and three py files)
>>> assert {'collections', 'asyncio', 'os', 'dis', '__future__'}.issubset(standard_lib_names)
>>> # verify that other decoys are not in there
>>> assert {'__pycache__', 'LICENSE.txt', 'config-3.8-darwin', '.DS_Store'}.isdisjoint(standard_lib_names)
>>>
>>> len(standard_lib_names)
200
>>>
>>> # not including underscored
>>> standard_lib_names = set(standard_lib_names_gen(include_underscored=False))
>>> len(standard_lib_names)
184

2
投票

这篇文章的旧副本中也有一个很好的答案:https://stackoverflow.com/a/28873415/7262247

这就是你可以做到的(你需要首先

pip install stdlib_list
):

from stdlib_list import stdlib_list
import sys

all_stdlib_symbols = stdlib_list('.'.join([str(v) for v in sys.version_info[0:2]]))

module_name = 'collections'

if module_name in all_stdlib_symbols:
    print("%s is in stdlib" % module_name)

0
投票

如果你想检查 stdlib 中是否存在实际实例类(不是它的名称),你可以这样做:

from inspect import isclass
from sys import stdlib_module_names

def is_in_stdlib(obj: object) -> bool:
    cls = obj if isclass(obj) else type(obj)
    return cls.__module__ in stdlib_module_names
© www.soinside.com 2019 - 2024. All rights reserved.