Re: Why generate POP_TOP after an "import from?"
On Sun, Apr 19, 2020 at 7:40 AM Adam Preble wrote: > > On Saturday, April 18, 2020 at 1:15:35 PM UTC-5, Alexandre Brault wrote: > > >>> def f(): > > ... â â from sys import path, argv ... > > So I figured it out and all but I wanted to ask about the special characters > in that output. I've seen that a few times and never figured out what's going > on and if I need to change how I'm reading these. Or say: > > â â â â â â â â â â â â 12 STORE_FASTâ â â â â â â â â â â â â â 1 (argv > > I don't know if you're seeing all these letter a's. I'm guessing something > goofy with Unicode spaces or something? > That looks like something got messed up between the various mailing list and newsgroup gateways. I'm not sure exactly what happened, but it's probably been converted into nonbreaking spaces, then encoded in some way, and decoded incorrectly. I'm not sure WHAT the encodings in question would be, but my best guess is that the nonbreaking spaces were encoded UTF-8 (C2 A0), and then decoded in some eight-bit encoding. ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Why generate POP_TOP after an "import from?"
On Sun, Apr 19, 2020 at 7:36 AM Adam Preble wrote: > > On Friday, April 17, 2020 at 1:37:18 PM UTC-5, Chris Angelico wrote: > > 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: > > Thanks for taking that on too. I haven't set up module hierarchy yet so I'm > not in a position to handle levels, but I have started parsing them and > generating the opcodes. Is it sufficient to just use the number of dots as an > indication of level? > Correct. You can literally just put that exact line of code into a function, disassemble it, and you'll see the level - even if you're not in a package (which would be a run-time error only). > As a side note, I suppose it's sufficient to just *peek* at the stack rather > than pop the module and push it again. I'm guessing that's what the Python > interpreter is doing. > Yep! > > 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. > > I'm trying to follow along for academic purposes. I'm guessing you mean that > would basically optimize: > > from sys import path > import sys > > It would definitely be a fringe thing to do... Exactly, an incredibly fringe thing to do :) But that's the effect you'd get (at least, I believe so - haven't actually tested that). ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Why generate POP_TOP after an "import from?"
On Saturday, April 18, 2020 at 1:15:35 PM UTC-5, Alexandre Brault wrote: > >>> def f(): > ... â â from sys import path, argv ... So I figured it out and all but I wanted to ask about the special characters in that output. I've seen that a few times and never figured out what's going on and if I need to change how I'm reading these. Or say: â â â â â â â â â â â â 12 STORE_FASTâ â â â â â â â â â â â â â 1 (argv I don't know if you're seeing all these letter a's. I'm guessing something goofy with Unicode spaces or something? -- https://mail.python.org/mailman/listinfo/python-list
Re: Why generate POP_TOP after an "import from?"
On Friday, April 17, 2020 at 1:37:18 PM UTC-5, Chris Angelico wrote: > 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: Thanks for taking that on too. I haven't set up module hierarchy yet so I'm not in a position to handle levels, but I have started parsing them and generating the opcodes. Is it sufficient to just use the number of dots as an indication of level? As a side note, I suppose it's sufficient to just *peek* at the stack rather than pop the module and push it again. I'm guessing that's what the Python interpreter is doing. > 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. I'm trying to follow along for academic purposes. I'm guessing you mean that would basically optimize: from sys import path import sys It would definitely be a fringe thing to do... -- https://mail.python.org/mailman/listinfo/python-list
Re: Why generate POP_TOP after an "import from?"
On 2020-04-17 2:22 p.m., Adam Preble 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? You can get an idea of what you're missing if you import multiple names from a module at once: >>> def f(): ... from sys import path, argv ... >>> dis.dis(f) 2 0 LOAD_CONST 1 (0) 2 LOAD_CONST 2 (('path', 'argv')) 4 IMPORT_NAME 0 (sys) 6 IMPORT_FROM 1 (path) 8 STORE_FAST 0 (path) 10 IMPORT_FROM 2 (argv) 12 STORE_FAST 1 (argv) 14 POP_TOP 16 LOAD_CONST 0 (None) 18 RETURN_VALUE As shown here (and confirmed by the doc of the IMPORT_FROM opcode), IMPORT_FROM loads an attribute from the module on top of the stack, but doesn't pop the module. The POP_TOP instruction is what does. -- https://mail.python.org/mailman/listinfo/python-list
Re: Why generate POP_TOP after an "import from?"
On Sat, Apr 18, 2020 at 4:26 AM Adam Preble 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
Re: Why generate POP_TOP after an "import from?"
On Friday, April 17, 2020 at 1:22:18 PM UTC-5, Adam Preble wrote: > 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? Check out this guy replying to himself 10 minutes later. I guess IMPORT_FROM pushes the module back on to the stack afterwards so that multiple import-from's can be executed off of it. This is then terminated with a POP_TOP: >>> def import_from_multi(): ... from sys import path, bar ... >>> dis(import_from_multi) 2 0 LOAD_CONST 1 (0) 2 LOAD_CONST 2 (('path', 'bar')) 4 IMPORT_NAME 0 (sys) 6 IMPORT_FROM 1 (path) 8 STORE_FAST 0 (path) 10 IMPORT_FROM 2 (bar) 12 STORE_FAST 1 (bar) 14 POP_TOP 16 LOAD_CONST 0 (None) 18 RETURN_VALUE -- https://mail.python.org/mailman/listinfo/python-list
Why generate POP_TOP after an "import from?"
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? -- https://mail.python.org/mailman/listinfo/python-list