On Sat, Apr 18, 2020 at 4:26 AM Adam Preble <[email protected]> wrote:
>
> Given this in Python 3.6.8:
>
> from dis import dis
>
> def import_from_test():
> from sys import path
>
> >>> dis(import_from_test)
> 2 0 LOAD_CONST 1 (0)
> 2 LOAD_CONST 2 (('path',))
> 4 IMPORT_NAME 0 (sys)
> 6 IMPORT_FROM 1 (path)
> 8 STORE_FAST 0 (path)
> 10 POP_TOP
> 12 LOAD_CONST 0 (None)
> 14 RETURN_VALUE
>
> I don't understand why there's a POP_TOP there that I don't get for an
> import_name grammatical statement.
>
> IMPORT_NAME needs to eat the top two entries of the stack for level and the
> from-list. BTW I don't know what level is for either since my science
> projects have always had it be zero, but that's another question.
>
> IMPORT_NAME will the push the module on to the stack.
>
> IMPORT_FROM will import path from the module on the stack, and push that
> result on the stack.
>
> STORE_FAST will store path for use, finally "modifying the namespace."
>
> At this point, my conceptual stack is empty. If I POP_TOP then I have nothing
> to pop and the world would end. Yet, it doesn't. What am I missing?
>
Good question, and nicely put, thank you. I like questions like this :)
Here's another function that can showcase a bit more of what's going on:
>>> def f():
... from . import foo, bar, baz
...
>>> dis.dis(f)
2 0 LOAD_CONST 1 (1)
2 LOAD_CONST 2 (('foo', 'bar', 'baz'))
4 IMPORT_NAME 0
6 IMPORT_FROM 1 (foo)
8 STORE_FAST 0 (foo)
10 IMPORT_FROM 2 (bar)
12 STORE_FAST 1 (bar)
14 IMPORT_FROM 3 (baz)
16 STORE_FAST 2 (baz)
18 POP_TOP
20 LOAD_CONST 0 (None)
22 RETURN_VALUE
The level is used for package-relative imports, and will basically be
the number of leading dots (eg "from ...spam import x" will have a
level of 3). You're absolutely right with your analysis, with one
small clarification:
> IMPORT_FROM will import path from the module on the stack, and push that
> result on the stack.
>
It leaves the module on the stack, allowing chained IMPORT_FROM
operations to grab multiples from the same module. That's why it needs
to be popped off at the end.
In theory, I suppose, you could replace the POP_TOP with a STORE_FAST
into "sys", and thus get a two-way import that both grabs the module
and also grabs something out of it. Not very often wanted, but could
be done if you fiddle with the bytecode.
ChrisA
--
https://mail.python.org/mailman/listinfo/python-list