确定给定的Python模块是否为内置modu

2024-09-27 23:25:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在对各种模块进行一些解析和内省,但我不想解析内置模块。现在,对于内置模块没有特殊的类型,比如有一个types.BuiltinFunctionType,那么我该怎么做呢?在

>>> import CornedBeef
>>> CornedBeef
<module 'CornedBeef' from '/meatish/CornedBeef.pyc'>
>>> CornedBeef.__file__
'/meatish/CornedBeef.pyc'
>>> del CornedBeef.__file__
>>> CornedBeef
<module 'CornedBeef' (built-in)>

根据Python,如果模块没有__file__属性,那么它显然是内置的。这是否意味着hasattr(SomeModule, '__file__')是检查模块是否内置的方法?当然,这对del SomeModule.__file__来说并不常见,但是有没有更可靠的方法来确定模块是否是内置的呢?在


Tags: 模块方法fromimport类型内置filetypes
3条回答

您可以使用imp.is_builtin来查看模块名是否与内置模块匹配,但我想不出任何方法来真正可靠地反省模块对象。在

您也可以尝试以下操作:

>>> import imp
>>> f, path, desc = imp.find_module("sys")
>>> desc
('', '', 6)
>>> desc[2] == imp.C_BUILTIN
True

^{}

A tuple of strings giving the names of all modules that are compiled into this Python interpreter. (This information is not available in any other way — modules.keys() only lists the imported modules.)

如果你认为它只是被问到,builtins,那么接受的答案显然是正确的。在

在我的例子中,我也在寻找标准库,我指的是给定Python发行版附带的所有可导入模块的列表。关于这方面的问题已经被问了好几次,但我找不到一个包括我所寻找的一切的答案。在

我的用例是在Python import x语句中插入任意一个x,如下所示:

  • 包含在Python stdlib+内置组件中
  • 作为第三方模块安装
  • 都不是

这将适用于virtualenvs或全局安装。它查询运行脚本的任何python二进制文件的分布。最后一块确实超出了virtualenv,但我认为这是期望的行为。在

# You may need to use setuptools.distutils depending on Python distribution.
import distutils
import glob
import os
import pkgutil
import sys    

def get_python_library():

    # Get list of the loaded source modules on sys.path.
    modules = { 
        module
        for _, module, package in list(pkgutil.iter_modules())
        if package is False
    }

    # Glob all the 'top_level.txt' files installed under site-packages.
    site_packages = glob.iglob(os.path.join(os.path.dirname(os.__file__) 
                    + '/site-packages', '*-info', 'top_level.txt'))

    # Read the files for the import names and remove them from the modules list.
    modules -= {open(txt).read().strip() for txt in site_packages}

    # Get the system packages.
    system_modules = set(sys.builtin_module_names)

    # Get the just the top-level packages from the python install.
    python_root = distutils.sysconfig.get_python_lib(standard_lib=True)
      _, top_level_libs, _ = list(os.walk(python_root))[0]

    return sorted(top_level_libs + list(modules | system_modules))

返回

已排序的导入列表:[..., 'imaplib', 'imghdr', 'imp', 'importlib', 'imputil', 'inspect', 'io', ...]

说明

我把它分成几块,这样每个小组需要的原因就可以很清楚了。在

  • modules

    • ^{}调用扫描sys.path上所有加载的模块,并返回(module_loader, name, ispkg)元组的生成器。在
    • 我把它转换成一个集合并过滤出包,因为这里我们只关心源模块。在
  • site_packages

    • 获取常规站点包目录下所有已安装包的列表,并从modules列表中删除它们。这大致相当于第三方DEP。在
    • 这是最难纠正的部分。很多东西几乎都起作用了,比如^{}或{}。但是pip返回的模块名称与PyPi上的一样,而不是导入到源文件中时的名称。某些病理包裹会从裂缝中滑出,比如:
      • requests-futures作为requests_futures导入。在
      • colors,这实际上是PyPi上的{},因此混淆了任何合理的启发式。在
    • 我确信某些低使用率模块在其包中不包括top_level.txt。我的所有案例都被正确配置了。在
  • system_modules

    • 如果不显式地请求它们,就不会得到这些系统模块,比如sysgcerrno和其他一些{a3}。在
  • top_level_libs

    • ^{}调用返回独立于平台的标准库的顶层目录。在
    • 它们很容易丢失,因为它们可能与其他模块不在同一python路径下。如果您在OSX上运行virtualenv,这些模块实际上将从系统安装中导入。这些模块包括emailloggingxml等。在

结论

对于我的2013 MacBookPro,我找到了403个模块用于python2.7安装。在

^{pr2}$

我提出了the code and output的要点。如果你认为我错过了一个类或包含了一个伪造的模块,我想听听。在

*备选方案

  • 在写这篇文章时,我对pip和{}API进行了深入的研究。这些信息可能通过单个模块传递,但您确实需要了解如何绕过该API。

  • 在我开始之前,有人告诉我,six有一个专门针对这个问题的函数。它可能存在,但我自己找不到。

相关问题 更多 >

    热门问题