If you checked Python C- API documentation about running python code via the C calls, you will always find mention to PyCompilerFlags
, but nothing really describes what is it except the last portion of documentation and says nothing about its possible values and their effect on execution.
PyCompilerFlags
is the C API equivalent to the flags argument passed to compile
and related functions in Python. This probably isn't at all obvious if you don't already know the Python docs forward and backward before looking at the CPython C-API docs.
From compile
:
The optional arguments flags and dont_inherit control which future statements affect the compilation of source. If neither is present (or both are zero) the code is compiled with those future statements that are in effect in the code that is calling
compile()
. If the flags argument is given and dont_inherit is not (or is zero) then the future statements specified by the flags argument are used in addition to those that would be used anyway. If dont_inherit is a non-zero integer then the flags argument is it – the future statements in effect around the call to compile are ignored.Future statements are specified by bits which can be bitwise ORed together to specify multiple statements. The bitfield required to specify a given feature can be found as the
compiler_flag
attribute on the_Feature
instance in the__future__
module.
Following the link to future statements gives more details on how they work, and the link to the __future__
has a chart showing the list of future statements available.
Another thing that may not be obvious: each future feature flag corresponds to a flag that ends up in the co_flags
attribute of a code
object. So:
code = compile('1 <> 2', '', 'eval', flags=__future__.barry_as_FLUFL.compiler_flag)
assert code.co_flags & CO_FUTURE_BARRY_AS_BDFL
In C, if you pass struct PyCompilerFlags flags = { CO_FUTURE_BARRY_AS_BDFL }
to get the same effect.
If you want to see the actual numeric values for those flags, you have to look up the corresponding CO_*
constants in the C source or in the __future__
source.
Things are slightly different in the C API, in a few ways.
PyRun_*
or PyCompile_*
call.PyCompile_Flags
struct holding an int, instead of a raw int. This is just for the purpose of type checking; in memory, a struct holding an int is stored the same way as an int.Let's look at a complete example. I'll use Python 2.7 even though I've been linking to 3.7 docs, just because an example using print
is simpler than one using forward annotations.
This code prints an empty tuple:
print()
But if you run the first one with PyRun_SimpleStringFlags
, passing CO_FUTURE_PRINT_FUNCTION
(0x10000) as the flags`, it will print a blank line, a la Python 3.
If you run this code:
from __future__ import print_function
print()
… then whether you passed in 0
or CO_FUTURE_PRINT_FUNCTION
, it will print a blank line. And after the call, if you look at the flags you passed in by reference, it will have that CO_FUTURE_PRINT_FUNCTION
or'd onto it. So, if you're compiling and running a chunk at a time, you can pass that same value along to the next string, and it'll inherit that future flag. (Much like when you write a future statement in the interactive interpreter, it affects all the statements you interpret after that.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With