What is the difference between load name and load global in python bytecode?

2024/9/30 11:33:41

load name takes its argument and pushes onto the stack the value of the name stored by store name at the position indicated by the argument . load global does something similar, but there appears to be no store global in the bytecode. So what is the difference and how does load global work

Answer

The difference between LOAD_NAME and LOAD_GLOBAL is where they search for a given name.

LOAD_NAME

When Python encounters a LOAD_NAME opcode:

  • It first searches in f_locals - the names local to the current frame object.
  • If it doesn't find the given name in f_locals, it then proceeds to search in f_globals - the global names of the frame object. These are the names in the surrounding scope of the frame object.
  • If doesn't find the name in f_globals, it then searches f_builtins. f_builtins is a dictionary of the builtin names Python uses.
  • If all of the above fails, Python raises a NameError.

Here the relevant C code where the virtual machine executes a LOAD_NAME instruction:

    TARGET(LOAD_NAME) {PyObject *name = GETITEM(names, oparg);PyObject *locals = f->f_locals;PyObject *v;if (locals == NULL) {PyErr_Format(PyExc_SystemError,"no locals when loading %R", name);goto error;}if (PyDict_CheckExact(locals)) {v = PyDict_GetItem(locals, name);Py_XINCREF(v);}else {v = PyObject_GetItem(locals, name);if (v == NULL) {if (!PyErr_ExceptionMatches(PyExc_KeyError))goto error;PyErr_Clear();}}if (v == NULL) {v = PyDict_GetItem(f->f_globals, name);Py_XINCREF(v);if (v == NULL) {if (PyDict_CheckExact(f->f_builtins)) {v = PyDict_GetItem(f->f_builtins, name);if (v == NULL) {format_exc_check_arg(PyExc_NameError,NAME_ERROR_MSG, name);goto error;}Py_INCREF(v);}else {v = PyObject_GetItem(f->f_builtins, name);if (v == NULL) {if (PyErr_ExceptionMatches(PyExc_KeyError))format_exc_check_arg(PyExc_NameError,NAME_ERROR_MSG, name);goto error;}}}}PUSH(v);DISPATCH();}

LOAD_GLOBAL

When Python encounters a LOAD_GLOBAL opcode:

  • Python first searches for the name in f_globals - the names in surrounding scopes that the current frame object references.
  • If doesn't find the name in f_globals, it then searches f_builtins. f_builtins is a dictionary of the builtin names Python uses.
  • If all of the above fails, Python raises a NameError.

Here the relevant C code where the virtual machine executes a LOAD_GLOBAL instruction:

    TARGET(LOAD_GLOBAL) {PyObject *name = GETITEM(names, oparg);PyObject *v;if (PyDict_CheckExact(f->f_globals)&& PyDict_CheckExact(f->f_builtins)){v = _PyDict_LoadGlobal((PyDictObject *)f->f_globals,(PyDictObject *)f->f_builtins,name);if (v == NULL) {if (!_PyErr_OCCURRED()) {/* _PyDict_LoadGlobal() returns NULL without raising* an exception if the key doesn't exist */format_exc_check_arg(PyExc_NameError,NAME_ERROR_MSG, name);}goto error;}Py_INCREF(v);}else {/* Slow-path if globals or builtins is not a dict *//* namespace 1: globals */v = PyObject_GetItem(f->f_globals, name);if (v == NULL) {if (!PyErr_ExceptionMatches(PyExc_KeyError))goto error;PyErr_Clear();/* namespace 2: builtins */v = PyObject_GetItem(f->f_builtins, name);if (v == NULL) {if (PyErr_ExceptionMatches(PyExc_KeyError))format_exc_check_arg(PyExc_NameError,NAME_ERROR_MSG, name);goto error;}}}PUSH(v);DISPATCH();}

So, what's the difference?

As you could probably see, the difference is that LOAD_GLOBAL skips straight to searching the global names of the frame object, whereas LOAD_NAME starts searching the local names and makes it way up. The LOAD_GLOBAL opcode is useful for the case where Python already knows that a name cannot be local, so it skips searching local names altogether.

Note: if your looking to learn more about how the Python virtual machine works, I looking over Byterun, a pure-python implementation of the CPython virtual machine. It also has an accompanying article by Allison Kaptur.

https://en.xdnf.cn/q/71093.html

Related Q&A

porting Python 2 program to Python 3, random line generator

I have a random line generator program written in Python2, but I need to port it to Python3. You give the program the option -n [number] and a file argument to tell it to randomly output [number] numbe…

Symbol not found, Expected in: flat namespace

I have a huge gl.pxd file with all the definitions of gl.h, glu.h and glut.h. For example it has these lines:cdef extern from <OpenGL/gl.h>:ctypedef unsigned int GLenumcdef void glBegin( GLenum m…

Why does Django not generate CSRF or Session Cookies behind a Varnish Proxy?

Running Django 1.2.5 on a Linux server with Apache2 and for some reason Django seems like it cannot store CSRF or Session cookies. Therefore when I try to login to the Django admin it gives me a CSRF v…

Shared state with aiohttp web server

My aiohttp webserver uses a global variable that changes over time:from aiohttp import web shared_item = blaasync def handle(request):if items[test] == val:shared_item = doedaprint(shared_item)app =…

ModuleNotFoundError: No module named matplotlib.pyplot

When making a plot, I used both Jupyter Notebook and Pycharm with the same set of code and packages. The code is: import pandas as pd import numpy as np import matplotlib.pyplot as plt # as in Pycha…

python linux - display image with filename as viewer window title

when I display an image with PIL Image it opens an imagemagick window but the title is some gibberish name like tmpWbfj48Bfjf. How do I make the image filename to be the title of the viewer window?

Request body serialization differences when lambda function invoked via API Gateway v Lambda Console

I have a simple API set up in AWS API Gateway. It is set to invoke a Python 2.7 lambda function via API Gateway Proxy integration.I hit a strange error in that the lambda worked (processed the body co…

Determining a homogeneous affine transformation matrix from six points in 3D using Python

I am given the locations of three points:p1 = [1.0, 1.0, 1.0] p2 = [1.0, 2.0, 1.0] p3 = [1.0, 1.0, 2.0]and their transformed counterparts:p1_prime = [2.414213562373094, 5.732050807568877, 0.7320508075…

Split datetime64 column into a date and time column in pandas dataframe

If I have a dataframe with the first column being a datetime64 column. How do I split this column into 2 new columns, a date column and a time column. Here is my data and code so far:DateTime,Actual,Co…

Django - Setting date as date input value

Im trying to set a date as the value of a date input in a form. But, as your may have guessed, its not working.Heres what I have in my template:<div class="form-group"><label for=&qu…