Note that there are some explanatory texts on larger screens.

plurals
  1. POPython Package Design And Circular Imports
    primarykey
    data
    text
    <p>I'm using Python 3.3.2 to write a package that encapsulates a filesystem. My project looks like this:</p> <pre><code>~/ python/ filesystem/ __init__.py file.py directory.py </code></pre> <p>With <code>PYTHONPATH=~/python</code>.</p> <p>The problem is, <code>file.py</code> needs <code>directory.py</code> (for example, for <code>File.get_directory()</code>), and <code>directory.py</code> needs <code>file.py</code> (for example, for <code>Directory.get_files()</code>), so I have a circular import.</p> <ol> <li>When I use <code>import directory</code> in <code>file.py</code>, and <code>import file</code> in <code>directory.py</code>, it only works when my working directory is <code>filesystem</code> (that is, when the imports are local).</li> <li>When I use <code>import filesystem.directory</code> in <code>file.py</code>, and <code>import filesystem.file</code> in <code>directory.py</code>, it works fine, except the aesthetic nuisance of writing <code>filesystem.file.File</code> and <code>filesystem.Directory.directory</code> all them time.</li> <li>Curiously, when I use <code>import filesystem.directory as directory</code> or <code>from filesystem.directory import Directory</code>, I get the circular import error <code>'module' object has no attribute 'directory'</code>. My guess is that while <code>import ...</code> is lazy, <code>import ... as</code> and <code>from ... import</code> attempt to evaluate the module and notice the circularity immediately.</li> <li>One way to solve this is to <code>import filesystem.directory</code> inside the functions that use it. Unfortunately, many of my methods use it, and importing it inside a class does not seem to work.</li> </ol> <p>This is solvable, of course: sucking it up and writing <code>filesystem.directory.Directory</code>; assigning an <code>__import__</code> to a global variable in the <code>__init__</code> method for all the other methods to use; defining <code>File</code> and <code>Directory</code> in the same file; and so on. But these are more compromises than solutions, so my questions still stand:</p> <ol> <li>How would you design a filesystem, where a file class uses the directory class, and vice versa?</li> <li>And more generally, how would you deal with (or avoid) circular imports?</li> </ol> <p>Thanks.</p> <p><strong>UPDATE [03.07.2013]</strong> (Mostly for discussion's sake)</p> <p>Another solution I came upon is some sort of forward declarations, with empty <code>file</code> and <code>directory</code> classes in a common header, followed by separate implementations (more like attributes addition). While the resulting design is very neat, the idea is more C++-ish than Pythonic.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload