Go Module looping import issues in Python

Source: Internet
Author: User

This article turns from: https://wiki.woodpecker.org.cn/moin/MiscItems/2008-11-25 issues

Cleven <[email protected]>

Reply to [email     protected] recipient     [email protected] Date      November 25, 2008 PM 12:01 keynote      [cpyug:72341] Issues with import nesting  

Read the "Python Source Code Analysis", the problem of nested import mentioned in the question still did not understand, you look at it.

[a.py] From B import Dclass C:pass[b.py] fromA import Cclass D:pass    

Why can't I load D when I execute a?

If you change a.py to: Import B.

What's going on here?

Robert Chen: An explanation

Robert Chen <[email protected]om> replies to [email     protected] recipient     [email protected] date      November 25, 2008 afternoon 1:41 keynote      [cpyug:72362] re:import nesting issues   

Well, this is related to Python's internal import mechanism, which is divided into several steps within the From B import D,python:

    1. Find Symbol "B"
    2. If symbol B is present, get the module object corresponding to symbol b <module b>

      • the object corresponding to the symbol "D" is obtained from b>

    3. if symbol B does not exist, create a new module object <module B Note that at this point, the module object's __dict__ is empty

      • P class= "line862" > Executes the expression in b.py, populates b>

      • from <module b> __dict__ to obtain the corresponding object "D", if "D" does not exist, then throws an exception

So the order of execution for this example is as follows:

1, the implementation of the a.py in the From B import DBecause the Python a.py is executed, there is no <module b> in the Sys.modules,First, create a Module object (<module b>) for b.py,Note that the module object created at this time is empty and there is nothing inside,After the module object is created inside Python, the execution b.py is parsed to populate the dict of <module b>. 2, execute b.py from a import c in the course of implementing b.py, you will encounter this sentence, Span id= "line-9" class= "anchor" > first check if Sys.modules <module is already present in this module cache,  because at this time the cache has not been cached <module a>, so similarly, Inside Python, a Module object (<module a>) is created for a.py,  3, re-execute a.py in from B import D  at this point, because the <module b> object that was created in the 1th step is already in the Sys.modules,  so directly got <module b>, But, notice, from the whole process, we know , then <module b> is still an empty object, inside nothing,  So the operation of getting the symbol "D" from this module throws an exception.  If this is only import B, because the "B" symbol already exists in sys.modules, it will not throw an exception. 

ZQ: Illustration

    • Jude Drawing: Pyimportflow.jude

Compile Trace

Diary of Hiter:

    • Research on the import of Python

The problem code is as follows:

a.py fromA import Bclass B (object):pthe >>> import ATraceback (most recent): File "& Lt;stdin> ", line 1, in <module> File"/home/john/pythonstudy/mypython/bin/a.py ", line 9, in <module>< c7> from A import bimporterror:cannot import name B>>>       

After reading the code, I found:byte code probably

9 0 Load_const 0 (-1)3 Load_const 1 ((' B ',))6 Import_name 0 (A)9 Import_from 1 (B)1 Store_name (B)Pop_top ten Load_const 2 (' B ')  Load_name 2 (object)  Build_tuple 1 Load_const 3 (<code object B at 0xb7a1fa88, file "a.py", line 10>)  Make_function 0 34 Build_class Store_name 1 (B)  Load_const 4 (' Hi ') " Print_item Print_newline Load_const 5 (None)  Return_value            
    • You can see the whole import process is: First import a, and then import a and then error.
    • The analysis found that the reason is: at import a, the virtual machine found Sys.modules (check in import_submodule) did not load a, and then new a module, the new module is empty, you need to add __ builtin__,__file__ attributes (when executing the next import, the new module's dict will be passed as globals (locals) to execute (A) bytecode), The virtual machine then joins the new module in Sys.modules, at which point the call stack for the VM is as follows: (the line number of the code may be incorrect because many debug output codes are added to the source code)

#0 pyimport_addmodule (name=0xbfd91673 "A") at python/import.c:617 <-------Pyimport_addmodule here#1 0x08106271 in Pyimport_execcodemoduleex (name=0xbfd91673 "A", co=0xb7da6748, pathname=0xbfd8f533 "A.pyc") at Python/i mport.c:653#2 0x08106c67 in Load_source_module (name=0xbfd91673 "A", pathname=0xbfd8f533 "A.pyc", Fp=0x821bd60) at Python/import.c: 963#3 0x081085cf in Load_module (name=0xbfd91673 "A", Fp=0x821bd60, Buf=0xbfd905d3 "a.py", type=1, loader=0x0) at Python/imp ort.c:1753#4 0x0810a39b in Import_submodule (mod=0x818c888, subname=0xbfd91673 "a", fullname=0xbfd91673 "a") at Python/import.c:24 <--------Import_submodule is here#5 0x081098bb in Load_next (mod=0x818c888, altmod=0x818c888, p_name=0xbfd91654, buf=0xbfd91673 "A", p_buflen=0xbfd9166c )At python/import.c:2234#6 0x08108e1c in Import_module_level (name=0x0, GLOBALS=0XB7DE82B4, LOCALS=0XB7DE82B4, fromlist=0x818c888, Level=-1) at python/import.c:2005#7 0x081093a1 in Pyimport_importmodulelevel (name=0xb7de115c "A", Globals=0xb7de82b4, LOCALS=0XB7DE82B4, fromlist= 0x818c888, Level=-1)At python/import.c:2076#8 0x080d8809 in builtin___import__ (self=0x0, Args=0xb7d9de34, kwds=0x0) at python/bltinmodule.c:47#9 0x0814d04b in Pycfunction_call (FUNC=0XB7DCF5AC, Arg=0xb7d9de34, kw=0x0) at objects/methodobject.c:77#10 0x08062974 in Pyobject_call (FUNC=0XB7DCF5AC, Arg=0xb7d9de34, kw=0x0) at objects/abstract.c:1861#11 0x080ecad2 in Pyeval_callobjectwithkeywords (FUNC=0XB7DCF5AC, Arg=0xb7d9de34, kw=0x0) at python/ceval.c:3446#12 0x080e7b33 in Pyeval_evalframeex (F=0X821BC04, throwflag=0) at python/ceval.c:2068#13 0x080eaf9e in Pyeval_evalcodeex (Co=0xb7d9ab08, GLOBALS=0XB7DE82B4, LOCALS=0XB7DE82B4, args=0x0, argcount=0, kws= 0x0, Kwcount=0,defs=0x0, defcount=0, closure=0x0) at python/ceval.c:2840#14 0x080e013e in Pyeval_evalcode (Co=0xb7d9ab08, GLOBALS=0XB7DE82B4, LOCALS=0XB7DE82B4) at python/ceval.c:494#15 0x08116ab0 in Run_mod (mod=0x8220378, filename=0x81653bb "<stdin>", GLOBALS=0XB7DE82B4, LOCALS=0XB7DE82B4, Flags=0xbfd92f70, ARENA=0X81C5CD8) at python/pythonrun.c:1273  #16 0x081151e1 in Pyrun_interactiveoneflags (fp=0xb7f4d440, FILENAME=0X81653BB " <stdin> ", flags=0xbfd92f70) at Python/pythonrun.c:792 #17 0x08114e54 in Pyrun _interactiveloopflags (fp=0xb7f4d440, filename=0x81653bb "<stdin>", flags=0xbfd92f70) at PYTHON/PYTHONRUN.C : 723 #18 0X08114CAC in Pyrun_anyfileexflags (fp=0xb7f4d440, FILENAME=0X81653BB " <stdin> ", closeit=0, flags=0xbfd92f70) at Python/pythonrun.c:692 #19 0x08059d60 in Py_main (Argc=1, argv=0xbfd93074) at Modules/main.c:523 #20 0x08058e26 In Main (argc=136033156, ARGV=0XB7DC37B4) at./modules/python.c:23      
    • You can create a new module and add it to sys.modules in the function Pyimport_execcodemoduleex, and then pass the dict of the new module as locals (globals) to the function that executes the A-byte code. When executing a bytecode, it is found that import_name A is required, and the virtual opportunity discovers that a is already present in the sys.modules, so it returns the module of a directly, and in the next import_from, it tries to find B from the module. At this time the module in the virtual machine only loaded __builtin__,__file__ properties, loading B's bytecode has not been executed (and can not be executed), so the virtual machine will throw an exception can not load B.

    • In the <python source code anatomy > Preface, the question is mentioned:

[a.py] From B import Dclass C:    pass[b.py] fromA import Cclass D: pass   

D cannot be loaded here, which is similar to the one raised at the beginning of this article.

Summarize:
The execution flow of the Import_name byte-code command is as follows
  1. Assuming that import a is required, the virtual machine first looks in sys.modules for a load of a,
  2. When found, the object is returned and the command ends;
  3. If not found, then the virtual opportunity to create a new module object,
  4. Then add the necessary attributes (builtin, etc.) to the module object.

  5. Then use the Dict in this module as globals (locals) to execute a,
  6. and then return

Go Module looping import issues in Python

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.