Python 如何反省激活了哪些语言功能?
How can Python introspect on which language features are activated?
在这个 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 问题中挖掘出来。要查询语言功能的激活状态,事实证明我应该查看的不仅仅是编译器标志,因为编译器实际上并没有将标志用于已经强制的功能。
您可以检查代码对象的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
根据 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)
检查它是否在调用您的模块中激活。
在这个 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 问题中挖掘出来。要查询语言功能的激活状态,事实证明我应该查看的不仅仅是编译器标志,因为编译器实际上并没有将标志用于已经强制的功能。
您可以检查代码对象的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
根据 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)
检查它是否在调用您的模块中激活。