python 判断注释符合规_python - 在Python中,如何判断模块是否来自C扩展? - 堆栈内存溢出...

@Cecil Curry的功能很棒。 两个小评论:首先, _elementtree示例使用我的Python 3.5.6副本引发TypeError 。 其次,正如@crld指出的那样,了解模块是否包含 C扩展也很有帮助,但更便携的版本可能会有所帮助。 因此,更通用的版本可能是:

import importlib

from importlib.machinery import ExtensionFileLoader, EXTENSION_SUFFIXES

import inspect

import os

import os.path

import pkgutil

from types import ModuleType

from typing import List

def is_builtin_module(module: ModuleType) -> bool:

"""

Is this module a built-in module, like ``os``?

Method is as per :func:`inspect.getfile`.

"""

return not hasattr(module, "__file__")

def contains_c_extension(module: ModuleType,

import_all_submodules: bool = True,

include_external_imports: bool = False,

seen: List[ModuleType] = None) -> bool:

"""

Extends :func:`is_c_extension` by asking: is this module, or any of its

submodules, a C extension?

Args:

module: Previously imported module object to be tested.

import_all_submodules: explicitly import all submodules of this module?

include_external_imports: check modules in other packages that this

module imports?

seen: used internally for recursion (to deal with recursive modules);

should be ``None`` when called by users

Returns:

bool: ``True`` only if this module or one of its submodules is a C

extension.

Examples:

.. code-block:: python

import logging

import _elementtree as et

import os

import arrow

import alembic

import django

import numpy

import numpy.core.multiarray as numpy_multiarray

log = logging.getLogger(__name__)

logging.basicConfig(level=logging.DEBUG) # be verbose

contains_c_extension(os) # False

contains_c_extension(et) # False

contains_c_extension(numpy) # True -- different from is_c_extension()

contains_c_extension(numpy_multiarray) # True

contains_c_extension(arrow) # False

contains_c_extension(alembic) # False

contains_c_extension(alembic, include_external_imports=True) # True

# ... this example shows that Alembic imports hashlib, which can import

# _hashlib, which is a C extension; however, that doesn't stop us (for

# example) installing Alembic on a machine with no C compiler

contains_c_extension(django)

""" # noqa

assert inspect.ismodule(module), '"{}" not a module.'.format(module)

if seen is None: # only true for the top-level call

seen = [] # type: List[ModuleType]

if module in seen: # modules can "contain" themselves

# already inspected; avoid infinite loops

return False

seen.append(module)

# Check the thing we were asked about

is_c_ext = is_c_extension(module)

log.info("Is module {!r} a C extension? {}".format(module, is_c_ext))

if is_c_ext:

return True

if is_builtin_module(module):

# built-in, therefore we stop searching it

return False

# Now check any children, in a couple of ways

top_level_module = seen[0]

top_path = os.path.dirname(top_level_module.__file__)

# Recurse using dir(). This picks up modules that are automatically

# imported by our top-level model. But it won't pick up all submodules;

# try e.g. for django.

for candidate_name in dir(module):

candidate = getattr(module, candidate_name)

try:

if not inspect.ismodule(candidate):

# not a module

continue

except Exception:

# e.g. a Django module that won't import until we configure its

# settings

log.error("Failed to test ismodule() status of {!r}".format(

candidate))

continue

if is_builtin_module(candidate):

# built-in, therefore we stop searching it

continue

candidate_fname = getattr(candidate, "__file__")

if not include_external_imports:

if os.path.commonpath([top_path, candidate_fname]) != top_path:

log.debug("Skipping, not within the top-level module's "

"directory: {!r}".format(candidate))

continue

# Recurse:

if contains_c_extension(

module=candidate,

import_all_submodules=False, # only done at the top level, below # noqa

include_external_imports=include_external_imports,

seen=seen):

return True

if import_all_submodules:

if not is_module_a_package(module):

log.debug("Top-level module is not a package: {!r}".format(module))

return False

# Otherwise, for things like Django, we need to recurse in a different

# way to scan everything.

# See https://stackoverflow.com/questions/3365740/how-to-import-all-submodules. # noqa

log.debug("Walking path: {!r}".format(top_path))

try:

for loader, module_name, is_pkg in pkgutil.walk_packages([top_path]): # noqa

if not is_pkg:

log.debug("Skipping, not a package: {!r}".format(

module_name))

continue

log.debug("Manually importing: {!r}".format(module_name))

try:

candidate = loader.find_module(module_name)\

.load_module(module_name) # noqa

except Exception:

# e.g. Alembic "autogenerate" gives: "ValueError: attempted

# relative import beyond top-level package"; or Django

# "django.core.exceptions.ImproperlyConfigured"

log.error("Package failed to import: {!r}".format(

module_name))

continue

if contains_c_extension(

module=candidate,

import_all_submodules=False, # only done at the top level # noqa

include_external_imports=include_external_imports,

seen=seen):

return True

except Exception:

log.error("Unable to walk packages further; no C extensions "

"detected so far!")

raise

return False

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值