0

I am writing a Python bytecode optimizer for a module that previously had a Cython tool-chain. While that may be deprecated by now, I encountered something strange while fiddling with it. Consider this simple piece of code:

from opcode import opmap

globals().update(opmap)

print(STORE_GLOBAL)

This should print 97, as STORE_GLOBAL is defined in opmap with its opcode(which is 97). Cython will tell me that STORE_GLOBAL is not defined, though:

Error compiling Cython file:
------------------------------------------------------------
...
from opcode import opmap

globals().update(opmap)

print(STORE_GLOBAL)
                 ^
------------------------------------------------------------

test.py:5:18: undeclared name not builtin: STORE_GLOBAL

The reason for that is pretty easy, I guess. I assume that it doesn't update the globals, so it does not know about STORE_GLOBAL now being a variable.

Is there a unhacky way to overcome this problem?

Cheers

hellerve
  • 508
  • 1
  • 6
  • 30

2 Answers2

2

The reason is that while cython modules have a global namespace that is exposed in python, this is namespace is only used to export python visible variables.

However, most variables are not visible to python. These variables are declared at compile time and are statically typed. It is assumed that any variable referenced that is not declared in the module is an error, rather hoping the variable will be added later to the module globals.

The only way to circumvent this is to refer to such variables via the modules globals. Not very elegant.

print(globals()["STORE_GLOBAL"])

The best alternatives are to import opmap and refer to the relevant values through that. Or to write out the values in opmap verbatim in your module.

Dunes
  • 37,291
  • 7
  • 81
  • 97
0

I don't know if this is documented anywhere, but I've found that if a name is declared in a global statement in any function in a Cython module, then in addition to the standard Python meaning of "this name should be read and written as a global variable in this function", it also has the side effect of allowing the name to be read as a global variable everywhere else in the module, suppressing the error in the question.

mhsmith
  • 6,675
  • 3
  • 41
  • 58