Python如何反省激活哪些语言功能?

时间:2019-01-26 20:31:56

标签: python python-2.7 python-2.x

在此Python 2.7代码中,什么应该代替GET_MY_COMPILER_FLAGS()

from __future__ import print_function

def ReportCompilerFlags():
    myFlags = GET_MY_COMPILER_FLAGS()  # how?
    import __future__
    for featureName in __future__.all_feature_names:
        thisFlag = getattr(__future__, featureName).compiler_flag
        print('File {fileName} has {featureName} turned {status}.'.format(
            fileName = __file__,
            featureName = featureName,
            status = 'ON' if (myFlags & thisFlag) else 'off',
        ))
ReportCompilerFlags()

所需的输出:

File /path/to/this/script.py has nested_scopes turned off.
File /path/to/this/script.py has generators turned off.
File /path/to/this/script.py has division turned off.
File /path/to/this/script.py has absolute_import turned off.
File /path/to/this/script.py has with_statement turned off.
File /path/to/this/script.py has print_function turned ON.
File /path/to/this/script.py has unicode_literals turned off.   

我知道我可以检查globals()来查看它是否包含适当命名的符号而不是查看标志,但是显然,这样可能会导致误报和误报。

更新:我更新了标题,以从经典的XY问题中挖掘出该问题。要查询语言功能的激活状态,事实证明,我不仅要查看编译器标志,因为编译器实际上并未将标志用于已经强制的功能。

2 个答案:

答案 0 :(得分:4)

您可以检查代码对象的co_flags。这包括所有__future__标志和一堆用于其他用途的标志,例如代码对象是否用于生成器。

import inspect

all_flags = inspect.currentframe().f_code.co_flags

请注意,这告诉您哪些标志处于活动状态,而不一定告诉您哪些功能处于活动状态。如果您的Python版本默认启用了某个功能,则可能不会设置其标志。您可以检查要素对象的getMandatoryRelease以确定默认情况下标志是否为开:

import sys

def on_by_default(feature):
    return feature.getMandatoryRelease() <= sys.version_info

此外,请确保您具有正确的代码对象。例如,如果将其包装在库函数中,则应确保没有查看库函数自己的标志:

import inspect
import types

def code_flags(target=None):
    """
    Returns code flags for the caller of this function, or for a
    specified code or frame object.
    """
    if target is None:
        target = inspect.currentframe().f_back
    if isinstance(target, types.FrameType):
        target = target.f_code
    return target.co_flags

答案 1 :(得分:1)

基于user2357112的回答和其他人的有用评论,这是我最后写的库函数:

import sys
import inspect
import __future__

def features(stackBack=0):
    featureStatus = set()
    frame = None
    for featureName in __future__.all_feature_names:
        feature = getattr( __future__, featureName)
        if feature.getMandatoryRelease() <= sys.version_info:
            activated = True
        else:
            if frame is None:
                frame = inspect.stack()[abs(stackBack) + 1][0]
            activated = (frame.f_code.co_flags & feature.compiler_flag) != 0
        if activated:
            featureStatus.add(featureName)
    return featureStatus

假设我将其另存为language.py。 Python 2.7.12和3.6.8的相应输出为:

$ python -c 'import language; print(language.features())'
set(['with_statement', 'generators', 'nested_scopes'])

$ python3 -c 'import language; print(language.features())'
{'unicode_literals', 'with_statement', 'print_function', 'absolute_import', 'generators', 'division', 'nested_scopes'}

一个典型的用例可能是测试'unicode_literals' in features()来检查您当前是否激活了该特定功能,或者测试'unicode_literals' in features(stackBack=1)来检查该功能在任何调用您的模块中是否处于活动状态。