<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>
<channel>
	<title>Comments on: Python IMPORT_NAME bytecode mystery</title>
	<atom:link href="http://blog.paulbonser.com/2008/04/14/python-import_name/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.paulbonser.com/2008/04/14/python-import_name/</link>
	<description>Paul Bonser's blog about programming, technology, and other stuff</description>
	<pubDate>Tue, 07 Oct 2008 19:30:05 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.2</generator>
		<item>
		<title>By: Thomas Lee &#187; The Internals of Python&#8217;s IMPORT_NAME Bytecode</title>
		<link>http://blog.paulbonser.com/2008/04/14/python-import_name/#comment-504</link>
		<dc:creator>Thomas Lee &#187; The Internals of Python&#8217;s IMPORT_NAME Bytecode</dc:creator>
		<pubDate>Mon, 14 Apr 2008 10:18:12 +0000</pubDate>
		<guid isPermaLink="false">http://blog.paulbonser.com/?p=73#comment-504</guid>
		<description>&lt;p&gt;[...] was originally planned as a response to this post by Paul Bonser, but grew a little unwieldy (and his comment submission form seems to be [...]&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>[...] was originally planned as a response to this post by Paul Bonser, but grew a little unwieldy (and his comment submission form seems to be [...]</p>]]></content:encoded>
	</item>
	<item>
		<title>By: Thomas Lee</title>
		<link>http://blog.paulbonser.com/2008/04/14/python-import_name/#comment-503</link>
		<dc:creator>Thomas Lee</dc:creator>
		<pubDate>Mon, 14 Apr 2008 09:50:57 +0000</pubDate>
		<guid isPermaLink="false">http://blog.paulbonser.com/?p=73#comment-503</guid>
		<description>&lt;p&gt;The documentation for &lt;strong&gt;import&lt;/strong&gt; solves this mystery (well, sort of!):&lt;/p&gt;

&lt;p&gt;http://docs.python.org/lib/built-in-funcs.html&lt;/p&gt;

&lt;p&gt;"Note that even though locals() and ['eggs'] are passed in as arguments, the &lt;strong&gt;import&lt;/strong&gt;() function does not set the local variable named eggs; this is done by subsequent code that is generated for the import statement. (In fact, the standard implementation does not use its locals argument at all, and uses its globals only to determine the package context of the import statement.)"&lt;/p&gt;

&lt;p&gt;Essentially, when the IMPORT_NAME is executed for 'from foo import bar, baz', the &lt;strong&gt;import&lt;/strong&gt; builtin is called with the fromlist (which is converted to a tuple of strings). to provide custom import handling for your Python programs. For example, you may want to prevent users of your program from writing scripts that import certain modules.&lt;/p&gt;

&lt;p&gt;The code in Python/ceval.c for IMPORT_NAME seems to back this up (I've annotated it with a few comments ...):&lt;/p&gt;

&lt;pre&gt;[code lang="c"]    case IMPORT_NAME:
        w = GETITEM(names, oparg);
        /* 1. LOCATE THE __import__ BUILTIN */
        x = PyDict_GetItemString(f-&#62;f_builtins, "__import__");
        if (x == NULL) {
            PyErr_SetString(PyExc_ImportError,
                    "__import__ not found");
            break;
        }
        Py_INCREF(x);
        v = POP();
        u = TOP();
        /* 2. BUILD THE LIST OF ARGUMENTS FOR __import__ USING THE fromlist, globals() AND locals() */
        if (PyInt_AsLong(u) != -1 &#124;&#124; PyErr_Occurred())
            w = PyTuple_Pack(5,
                    w,
                    f-&#62;f_globals,
                    f-&#62;f_locals == NULL ?
                      Py_None : f-&#62;f_locals,
                    v,
                    u);
        else
            w = PyTuple_Pack(4,
                    w,
                    f-&#62;f_globals,
                    f-&#62;f_locals == NULL ?
                      Py_None : f-&#62;f_locals,
                    v);
        Py_DECREF(v);
        Py_DECREF(u);
        if (w == NULL) {
            u = POP();
            Py_DECREF(x);
            x = NULL;
            break;
        }
        READ_TIMESTAMP(intr0);
        v = x;
        /* 3. CALL __import__ */
        x = PyEval_CallObject(v, w);
        Py_DECREF(v);
        READ_TIMESTAMP(intr1);
        Py_DECREF(w);
        SET_TOP(x);
        if (x != NULL) continue;
        break;
[/code]&lt;/pre&gt;

&lt;p&gt;(hope the code looks okay - you need a "preview" feature :P)&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>The documentation for <strong>import</strong> solves this mystery (well, sort of!):</p>

<p><a href="http://docs.python.org/lib/built-in-funcs.html" rel="nofollow">http://docs.python.org/lib/built-in-funcs.html</a></p>

<p>&#8220;Note that even though locals() and ['eggs'] are passed in as arguments, the <strong>import</strong>() function does not set the local variable named eggs; this is done by subsequent code that is generated for the import statement. (In fact, the standard implementation does not use its locals argument at all, and uses its globals only to determine the package context of the import statement.)&#8221;</p>

<p>Essentially, when the IMPORT_NAME is executed for &#8216;from foo import bar, baz&#8217;, the <strong>import</strong> builtin is called with the fromlist (which is converted to a tuple of strings). to provide custom import handling for your Python programs. For example, you may want to prevent users of your program from writing scripts that import certain modules.</p>

<p>The code in Python/ceval.c for IMPORT_NAME seems to back this up (I&#8217;ve annotated it with a few comments &#8230;):</p>

<pre><div class="codesnip-container" ><div class="codesnip" style="font-family: monospace;"><span class="kw1">case</span> IMPORT_NAME:<br />
&nbsp; &nbsp; &nbsp; &nbsp; w = GETITEM<span class="br0">&#40;</span>names, oparg<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="coMULTI">/* 1. LOCATE THE __import__ BUILTIN */</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; x = PyDict_GetItemString<span class="br0">&#40;</span>f-&amp;gt;f_builtins, <span class="st0">&quot;__import__&quot;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>x == <span class="kw2">NULL</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PyErr_SetString<span class="br0">&#40;</span>PyExc_ImportError,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;__import__ not found&quot;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Py_INCREF<span class="br0">&#40;</span>x<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; v = POP<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; u = TOP<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="coMULTI">/* 2. BUILD THE LIST OF ARGUMENTS FOR __import__ USING THE fromlist, globals() AND locals() */</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>PyInt_AsLong<span class="br0">&#40;</span>u<span class="br0">&#41;</span> != <span class="nu0">-1</span> || PyErr_Occurred<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; w = PyTuple_Pack<span class="br0">&#40;</span><span class="nu0">5</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; w,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f-&amp;gt;f_globals,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f-&amp;gt;f_locals == <span class="kw2">NULL</span> ?<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Py_None : f-&amp;gt;f_locals,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; v,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; u<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; w = PyTuple_Pack<span class="br0">&#40;</span><span class="nu0">4</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; w,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f-&amp;gt;f_globals,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f-&amp;gt;f_locals == <span class="kw2">NULL</span> ?<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Py_None : f-&amp;gt;f_locals,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; v<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Py_DECREF<span class="br0">&#40;</span>v<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Py_DECREF<span class="br0">&#40;</span>u<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>w == <span class="kw2">NULL</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; u = POP<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Py_DECREF<span class="br0">&#40;</span>x<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x = <span class="kw2">NULL</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; READ_TIMESTAMP<span class="br0">&#40;</span>intr0<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; v = x;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="coMULTI">/* 3. CALL __import__ */</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; x = PyEval_CallObject<span class="br0">&#40;</span>v, w<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Py_DECREF<span class="br0">&#40;</span>v<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; READ_TIMESTAMP<span class="br0">&#40;</span>intr1<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Py_DECREF<span class="br0">&#40;</span>w<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; SET_TOP<span class="br0">&#40;</span>x<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>x != <span class="kw2">NULL</span><span class="br0">&#41;</span> <span class="kw1">continue</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;</div></div></pre>

<p>(hope the code looks okay - you need a &#8220;preview&#8221; feature :P)</p>]]></content:encoded>
	</item>
</channel>
</rss>
