Consider the following directory structure (Python 3):<div><br></div><div>[test]</div><div>    main.py</div><div>    [tree]</div><div>        __init__.py # empty</div><div>        branch.py</div><div>        root.py<br clear="all">
<div><br></div><div>main.py:</div><div><div class="hlcode" style="font-family:'Times New Roman';background-color:rgb(255,255,255);font-size:medium"><div class="syntax" style="background-image:initial;background-color:rgb(240,240,240);margin-top:15px;margin-bottom:10px;border-top-width:1px;border-top-style:solid;border-top-color:rgb(204,204,204);border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);background-repeat:initial initial">
<pre style="background-color:transparent;border-top-style:none;border-bottom-style:none;padding-top:10px;padding-right:10px;padding-bottom:10px;padding-left:10px;font-size:13px;font-family:'Bitstream Vera Sans Mono',monospace;margin-top:0px;margin-bottom:0px;border-right-style:none;border-left-style:none;border-width:initial;border-color:initial;overflow-x:auto;overflow-y:auto">
<span class="nb" style="color:rgb(0,112,32)">print</span><span class="p">(</span><span class="s" style="color:rgb(64,112,160)">'main: Entered the module'</span><span class="p">)</span>

<span class="nb" style="color:rgb(0,112,32)">print</span><span class="p">(</span><span class="s" style="color:rgb(64,112,160)">'main: from tree import root'</span><span class="p">)</span>
<span class="kn" style="color:rgb(0,112,32);font-weight:bold">from</span> <span class="nn" style="color:rgb(14,132,181);font-weight:bold">tree</span> <span class="k" style="color:rgb(0,112,32);font-weight:bold">import</span> <span class="n">root</span> <span class="c" style="color:rgb(96,160,176);font-style:italic"># this first finished importing module 'tree.root'</span>
<span class="c" style="color:rgb(96,160,176);font-style:italic"># then creates local name 'root' which references that imported module</span>
<span class="c" style="color:rgb(96,160,176);font-style:italic"># Why not creating local name 'root' at the same time when sys.modules['tree.root'] is created?</span>
<span class="c" style="color:rgb(96,160,176);font-style:italic"># If import fails:</span>
<span class="c" style="color:rgb(96,160,176);font-style:italic"># - either delete the attribute 'root'</span>
<span class="c" style="color:rgb(96,160,176);font-style:italic"># - or leave it - how it affects the runtime?</span>
<span class="kn" style="color:rgb(0,112,32);font-weight:bold">from</span> <span class="nn" style="color:rgb(14,132,181);font-weight:bold">tree</span> <span class="k" style="color:rgb(0,112,32);font-weight:bold">import</span> <span class="n">branch</span>

<span class="nb" style="color:rgb(0,112,32)">print</span><span class="p">(</span><span class="s" style="color:rgb(64,112,160)">'main: Creating a root and a leaf attached to it'</span><span class="p">)</span>

<span class="n">_root</span> <span class="o" style="color:rgb(102,102,102)">=</span> <span class="n">root</span><span class="o" style="color:rgb(102,102,102)">.</span><span class="n">Root</span><span class="p">()</span>
<span class="n">_branch</span> <span class="o" style="color:rgb(102,102,102)">=</span> <span class="n">branch</span><span class="o" style="color:rgb(102,102,102)">.</span><span class="n">Branch</span><span class="p">(</span><span class="n">_root</span><span class="p">)</span></pre>
</div></div></div><div><br></div><div>branch.py:</div><div><div class="hlcode" style="font-family:'Times New Roman';background-color:rgb(255,255,255);font-size:medium"><div class="syntax" style="background-image:initial;background-color:rgb(240,240,240);margin-top:15px;margin-bottom:10px;border-top-width:1px;border-top-style:solid;border-top-color:rgb(204,204,204);border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);background-repeat:initial initial">
<pre style="background-color:transparent;border-top-style:none;border-bottom-style:none;padding-top:10px;padding-right:10px;padding-bottom:10px;padding-left:10px;font-size:13px;font-family:'Bitstream Vera Sans Mono',monospace;margin-top:0px;margin-bottom:0px;border-right-style:none;border-left-style:none;border-width:initial;border-color:initial;overflow-x:auto;overflow-y:auto">
<span class="nb" style="color:rgb(0,112,32)">print</span><span class="p">(</span><span class="s" style="color:rgb(64,112,160)">'tree.branch: Entered the module'</span><span class="p">)</span>

<span class="kn" style="color:rgb(0,112,32);font-weight:bold">import</span> <span class="nn" style="color:rgb(14,132,181);font-weight:bold">tree</span><span class="o" style="color:rgb(102,102,102)">,</span> <span class="nn" style="color:rgb(14,132,181);font-weight:bold">sys</span>
<span class="nb" style="color:rgb(0,112,32)">print</span><span class="p">(</span><span class="s" style="color:rgb(64,112,160)">"tree.branch: 'root' in dir(tree) ->"</span><span class="p">,</span> <span class="s" style="color:rgb(64,112,160)">'root'</span> <span class="ow" style="color:rgb(0,112,32);font-weight:bold">in</span> <span class="nb" style="color:rgb(0,112,32)">dir</span><span class="p">(</span><span class="n">tree</span><span class="p">))</span>
<span class="nb" style="color:rgb(0,112,32)">print</span><span class="p">(</span><span class="s" style="color:rgb(64,112,160)">"tree.branch: 'tree.root' in sys.modules ->"</span><span class="p">,</span> <span class="s" style="color:rgb(64,112,160)">'tree.root'</span> <span class="ow" style="color:rgb(0,112,32);font-weight:bold">in</span> <span class="n">sys</span><span class="o" style="color:rgb(102,102,102)">.</span><span class="n">modules</span><span class="p">)</span>

<span class="nb" style="color:rgb(0,112,32)">print</span><span class="p">(</span><span class="s" style="color:rgb(64,112,160)">'tree.branch: from tree import root'</span><span class="p">)</span>
<span class="c" style="color:rgb(96,160,176);font-style:italic">#from tree import root # ImportError: cannot import name root </span>
<span class="kn" style="color:rgb(0,112,32);font-weight:bold">import</span> <span class="nn" style="color:rgb(14,132,181);font-weight:bold">tree.root</span> <span class="c" style="color:rgb(96,160,176);font-style:italic"># workaround</span>
<span class="n">root</span> <span class="o" style="color:rgb(102,102,102)">=</span> <span class="n">sys</span><span class="o" style="color:rgb(102,102,102)">.</span><span class="n">modules</span><span class="p">[</span><span class="s" style="color:rgb(64,112,160)">'tree.root'</span><span class="p">]</span> <span class="c" style="color:rgb(96,160,176);font-style:italic"># though name 'root' does not exist yet in module 'tree', sys.modules['root.tree'] already does</span>

<span class="nb" style="color:rgb(0,112,32)">print</span><span class="p">(</span><span class="s" style="color:rgb(64,112,160)">'tree.branch: Defining class branch.Branch()'</span><span class="p">)</span>

<span class="k" style="color:rgb(0,112,32);font-weight:bold">class</span> <span class="nc" style="color:rgb(14,132,181);font-weight:bold">Branch</span><span class="p">():</span>
    <span class="k" style="color:rgb(0,112,32);font-weight:bold">def</span> <span class="nf" style="color:rgb(6,40,126)">__init__</span><span class="p">(</span><span class="bp" style="color:rgb(0,112,32)">self</span><span class="p">,</span> <span class="n">_parent</span><span class="p">):</span>
        <span class="k" style="color:rgb(0,112,32);font-weight:bold">assert</span> <span class="nb" style="color:rgb(0,112,32)">isinstance</span><span class="p">(</span><span class="n">_parent</span><span class="p">,</span> <span class="n">root</span><span class="o" style="color:rgb(102,102,102)">.</span><span class="n">Root</span><span class="p">),</span> <span class="s" style="color:rgb(64,112,160)">'Pass a `Root` instance'</span></pre>
</div></div></div><div><br></div><div>root.py:</div><div><div class="hlcode" style="font-family:'Times New Roman';background-color:rgb(255,255,255);font-size:medium"><div class="syntax" style="background-image:initial;background-color:rgb(240,240,240);margin-top:15px;margin-bottom:10px;border-top-width:1px;border-top-style:solid;border-top-color:rgb(204,204,204);border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);background-repeat:initial initial">
<pre style="background-color:transparent;border-top-style:none;border-bottom-style:none;padding-top:10px;padding-right:10px;padding-bottom:10px;padding-left:10px;font-size:13px;font-family:'Bitstream Vera Sans Mono',monospace;margin-top:0px;margin-bottom:0px;border-right-style:none;border-left-style:none;border-width:initial;border-color:initial;overflow-x:auto;overflow-y:auto">
<span class="nb" style="color:rgb(0,112,32)">print</span><span class="p">(</span><span class="s" style="color:rgb(64,112,160)">'tree.root: Entered the module'</span><span class="p">)</span>

<span class="nb" style="color:rgb(0,112,32)">print</span><span class="p">(</span><span class="s" style="color:rgb(64,112,160)">'tree.root: from tree import branch'</span><span class="p">)</span>
<span class="kn" style="color:rgb(0,112,32);font-weight:bold">from</span> <span class="nn" style="color:rgb(14,132,181);font-weight:bold">tree</span> <span class="k" style="color:rgb(0,112,32);font-weight:bold">import</span> <span class="n">branch</span>

<span class="nb" style="color:rgb(0,112,32)">print</span><span class="p">(</span><span class="s" style="color:rgb(64,112,160)">'tree.root: Defining class Root()'</span><span class="p">)</span>

<span class="k" style="color:rgb(0,112,32);font-weight:bold">class</span> <span class="nc" style="color:rgb(14,132,181);font-weight:bold">Root</span><span class="p">():</span>
    <span class="k" style="color:rgb(0,112,32);font-weight:bold">def</span> <span class="nf" style="color:rgb(6,40,126)">attach</span><span class="p">(</span><span class="bp" style="color:rgb(0,112,32)">self</span><span class="p">,</span> <span class="n">_branch</span><span class="p">):</span>
        <span class="k" style="color:rgb(0,112,32);font-weight:bold">assert</span> <span class="nb" style="color:rgb(0,112,32)">isinstance</span><span class="p">(</span><span class="n">_branch</span><span class="p">,</span> <span class="n">branch</span><span class="o" style="color:rgb(102,102,102)">.</span><span class="n">Branch</span><span class="p">),</span> <span class="s" style="color:rgb(64,112,160)">'Pass a `Branch` instance'</span>
        <span class="bp" style="color:rgb(0,112,32)">self</span><span class="o" style="color:rgb(102,102,102)">.</span><span class="n">branch</span> <span class="o" style="color:rgb(102,102,102)">=</span> <span class="n">_branch</span></pre>
</div></div></div><div><br></div><div>Running it:</div><div><div class="hlcode" style="font-family:'Times New Roman';background-color:rgb(255,255,255);font-size:medium"><div class="syntax" style="background-image:initial;background-color:rgb(240,240,240);margin-top:15px;margin-bottom:10px;border-top-width:1px;border-top-style:solid;border-top-color:rgb(204,204,204);border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);background-repeat:initial initial">
<pre style="background-color:transparent;border-top-style:none;border-bottom-style:none;padding-top:10px;padding-right:10px;padding-bottom:10px;padding-left:10px;font-size:13px;font-family:'Bitstream Vera Sans Mono',monospace;margin-top:0px;margin-bottom:0px;border-right-style:none;border-left-style:none;border-width:initial;border-color:initial;overflow-x:auto;overflow-y:auto">
<span class="gp" style="color:rgb(198,93,9);font-weight:bold">vic@wic:~/projects/test$</span> python3 main.py 
<span class="go" style="color:rgb(128,128,128)">main: Entered the module</span>
<span class="go" style="color:rgb(128,128,128)">main: from tree import root</span>
<span class="go" style="color:rgb(128,128,128)">tree.root: Entered the module</span>
<span class="go" style="color:rgb(128,128,128)">tree.root: from tree import branch</span>
<span class="go" style="color:rgb(128,128,128)">tree.branch: Entered the module</span>
<span class="go" style="color:rgb(128,128,128)">tree.branch: 'root' in dir(tree) -> False</span>
<span class="go" style="color:rgb(128,128,128)">tree.branch: 'tree.root' in sys.modules -> True</span>
<span class="go" style="color:rgb(128,128,128)">tree.branch: from tree import root</span>
<span class="go" style="color:rgb(128,128,128)">tree.branch: Defining class branch.Branch()</span>
<span class="go" style="color:rgb(128,128,128)">tree.root: Defining class Root()</span>
<span class="go" style="color:rgb(128,128,128)">main: Creating a root and a leaf attached to it</span></pre></div></div></div><div><br></div><div>So,</div><div>There are circular imports in this example code. </div><div>
Currently, `root = sys.modules['tree.root']` hack in branch.py works.</div><div>Wouldn't it be useful to create attribute `root` in `main` at the same time `sys.modules['tree.root']` is created when doing `from tree import root` in main?</div>
<div>This would solve more complex cases with when circular imports are involved, without applying such hacks. </div><div><br></div><div>Thank you</div><div>--</div><b><i>Victor </i></b><br><br>
</div>