Python bytecode STORE_NAME

Peter Otten __peter__ at web.de
Wed Nov 19 10:58:54 EST 2008


schwarz at cs.au.dk wrote:

> On 19 Nov., 10:14, Peter Otten <__pete... at web.de> wrote:
>>
>> Every code object has its own co_names attribute (a tuple). The arguments
>> are offsets into that tuple.
>>
>> Using Python 2.5 I can't reproduce your example, I get 0 offsets in both
>> cases. Here's a simpler one:
>>
>> >>> import dis
>> >>> def f():
>>
>> ...     x
>> ...     y
>> ...>>> def g():
>>
>> ...     y
>> ...>>> dis.dis(f)
>>
>> 2           0 LOAD_GLOBAL              0 (x)
>> 3 POP_TOP
>>
>> 3           4 LOAD_GLOBAL              1 (y)
>> 7 POP_TOP
>> 8 LOAD_CONST               0 (None)
>> 11 RETURN_VALUE>>> dis.dis(g)
>>
>> 2           0 LOAD_GLOBAL              0 (y)
>> 3 POP_TOP
>> 4 LOAD_CONST               0 (None)
>> 7 RETURN_VALUE>>> f.func_code.co_names
>> ('x', 'y')
>> >>> g.func_code.co_names
>>
>> ('y',)
>>
>> Peter
> 
> Ok, thanks a lot. That helped me understand the offsets. Your
> disassembly misses the code in the global scope that creates the two
> methods from the code objects. That code looks like this for your
> example (dis won't give you this. I use a modified version of the
> byteplay disassembler which can disassemble a module without loading
> it):
> 1, LOAD_CONST, 1 //Loads the code object for function f
> 4, MAKE_FUNCTION, 0 //Creates a function from the code object
> 7, STORE_NAME, 0 //Stores it as 'f' using STORE_NAME
> 10, LOAD_CONST, 2 //Loads the code object for function g
> 13, MAKE_FUNCTION, 0 //Creates the function
> 16, STORE_NAME, 1 //Stores it as 'g' using STORE_NAME
> 19, LOAD_CONST, 0 //Loads None
> 22, RETURN_VALUE, None //Exists the program with status None

You can get it with standard tools, too:

$ cat tmp.py
def f():
    x
    y

def g():
    x
$ python -c'import tmp'
$ python
Python 2.5.1 (r251:54863, Jul 31 2008, 23:17:43)
[GCC 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import marshal
>>> module = marshal.loads(open("tmp.pyc").read()[8:])
>>> import dis
>>> dis.dis(module)
  1           0 LOAD_CONST               0 (<code object f at
0x2b3389f3d648, file "tmp.py", line 1>)
              3 MAKE_FUNCTION            0
              6 STORE_NAME               0 (f)

  5           9 LOAD_CONST               1 (<code object g at
0x2b3389f3d828, file "tmp.py", line 5>)
             12 MAKE_FUNCTION            0
             15 STORE_NAME               1 (g)
             18 LOAD_CONST               2 (None)
             21 RETURN_VALUE

I just didn't deem it relevant.

> The two last bytecodes are there because I didn't use the interactive
> mode. I guess I narrowed down my other question to whether the
> semantics are that stuff saved using STORE_NAME in the global scope
> can be loaded everywhere else using LOAD_GLOBAL. What baffled me was
> that there is actually a STORE_GLOBAL byte code.

If you are really interested in the subtleties you have to dive into the
source. After a quick look into

http://svn.python.org/view/python/trunk/Python/ceval.c?rev=63675&view=markup

I think STORE_NAME works with the module startup code because global and
local namespace are identical. Within a function (with distinct global and
local namespaces) you'd have to use STORE_GLOBAL.

Peter



More information about the Python-list mailing list