Xavier de Gaye <xdeg...@gmail.com> added the comment:

In msg360620 Serhiy wrote:
> When the interpreter encounters "import foo" in bar.py, the import machinery 
> takes the module foo from sys.modules.
> So you break an infinite cycle and can import modules with cyclic 
> dependencies.

The following pdb session that is run when executing the foo.py script, shows 
that this is not quite accurate.  When the interpreter encounters "import foo" 
in bar.py, the import machinery instead starts executing foo.py once again and 
detects that at line 9 of foo.py the 'import bar' statement does not have to be 
executed since the import machinery is already in the process of importing this 
module.  So it is at that point that the infinite cycle is broken.
Later on line 12 in foo.py the import machinery detects that the AttributeError 
is raised because of a circular import and warns that "partially initialized 
module 'bar' has no attribute 'BAR' (most likely due to a circular import)".

$ cat -n foo.py
     1  import pdb
     2  debug = 1
     3
     4  # Prevent starting a new pdb session when foo is imported by bar.
     5  if debug and not hasattr(pdb, 'is_pdb_started'):
     6      pdb.Pdb(skip=['importlib*']).set_trace()
     7      pdb.is_pdb_started = True
     8
     9  import bar
    10  FOO = 'foo'
    11  try:
    12      print(bar.BAR)
    13  except AttributeError as e:
    14      # The exception is raised with an explicit reason when foo is 
imported by
    15      # bar due to partially initialized module 'bar'.
    16      print(e)

$ cat -n bar.py
     1  import foo
     2  BAR = 'bar'
     3  print(foo.FOO)

$ python foo.py
> /tmp/foo.py(7)<module>()
-> pdb.is_pdb_started = True
(Pdb) step
> /tmp/foo.py(9)<module>()
-> import bar
(Pdb) step
--Call--
> /tmp/bar.py(1)<module>()
-> import foo
(Pdb) step
> /tmp/bar.py(1)<module>()
-> import foo
(Pdb) step
--Call--
> /tmp/foo.py(1)<module>()
-> import pdb
(Pdb) step
> /tmp/foo.py(1)<module>()
-> import pdb
(Pdb) step
> /tmp/foo.py(2)<module>()
-> debug = 1
(Pdb) step
> /tmp/foo.py(5)<module>()
-> if debug and not hasattr(pdb, 'is_pdb_started'):
(Pdb) step
> /tmp/foo.py(9)<module>()
-> import bar
(Pdb) step
> /tmp/foo.py(10)<module>()
-> FOO = 'foo'
(Pdb) step
> /tmp/foo.py(11)<module>()
-> try:
(Pdb) step
> /tmp/foo.py(12)<module>()
-> print(bar.BAR)
(Pdb) step
AttributeError: partially initialized module 'bar' has no attribute 'BAR' (most 
likely due to a circular import)
> /tmp/foo.py(12)<module>()
-> print(bar.BAR)
(Pdb) step
> /tmp/foo.py(13)<module>()
-> except AttributeError as e:
(Pdb) step
> /tmp/foo.py(16)<module>()
-> print(e)
(Pdb) step
partially initialized module 'bar' has no attribute 'BAR' (most likely due to a 
circular import)
--Return--
> /tmp/foo.py(16)<module>()->None
-> print(e)
(Pdb) step
> /tmp/bar.py(2)<module>()
-> BAR = 'bar'
(Pdb) step
> /tmp/bar.py(3)<module>()
-> print(foo.FOO)
(Pdb) step
foo
--Return--
> /tmp/bar.py(3)<module>()->None
-> print(foo.FOO)
(Pdb) step
> /tmp/foo.py(10)<module>()
-> FOO = 'foo'
(Pdb) step
> /tmp/foo.py(11)<module>()
-> try:
(Pdb) step
> /tmp/foo.py(12)<module>()
-> print(bar.BAR)
(Pdb) step
bar
--Return--
> /tmp/foo.py(12)<module>()->None
-> print(bar.BAR)
(Pdb) step
$

----------
nosy: +xdegaye

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue39430>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to