Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>This is what I justed in my unittests.</p> <p>It uses <a href="http://docs.python.org/release/2.3.5/whatsnew/section-pep302.html" rel="nofollow noreferrer">PEP-302 "New Import Hooks"</a>. (Warning: the PEP-302 document and the more concise release notes I linked aren't exactly <em>accurate</em>.)</p> <p>I use <code>meta_path</code> because it's as early as possible in the import sequence.</p> <p>If the module has already been imported (as in my case, because earlier unittests mock against it), then it's necessary to remove it from sys.modules before doing the <code>reload</code> on the dependent module.</p> <pre><code>Ensure we fallback to using ~/.pif if XDG doesn't exist. &gt;&gt;&gt; import sys &gt;&gt;&gt; class _(): ... def __init__(self, modules): ... self.modules = modules ... ... def find_module(self, fullname, path=None): ... if fullname in self.modules: ... raise ImportError('Debug import failure for %s' % fullname) &gt;&gt;&gt; fail_loader = _(['xdg.BaseDirectory']) &gt;&gt;&gt; sys.meta_path.append(fail_loader) &gt;&gt;&gt; del sys.modules['xdg.BaseDirectory'] &gt;&gt;&gt; reload(pif.index) #doctest: +ELLIPSIS &lt;module 'pif.index' from '...'&gt; &gt;&gt;&gt; pif.index.CONFIG_DIR == os.path.expanduser('~/.pif') True &gt;&gt;&gt; sys.meta_path.remove(fail_loader) </code></pre> <p>Where the code inside pif.index looks like:</p> <pre><code>try: import xdg.BaseDirectory CONFIG_DIR = os.path.join(xdg.BaseDirectory.xdg_data_home, 'pif') except ImportError: CONFIG_DIR = os.path.expanduser('~/.pif') </code></pre> <hr> <p>To answer the question about why the newly reloaded module has properties of the old and new loads, here are two example files.</p> <p>The first is a module <code>y</code> with an import failure case.</p> <pre><code># y.py try: import sys _loaded_with = 'sys' except ImportError: import os _loaded_with = 'os' </code></pre> <p>The second is <code>x</code> which demonstrates how leaving handles about for a module can affect its properties when being reloaded.</p> <pre><code># x.py import sys import y assert y._loaded_with == 'sys' assert y.sys class _(): def __init__(self, modules): self.modules = modules def find_module(self, fullname, path=None): if fullname in self.modules: raise ImportError('Debug import failure for %s' % fullname) # Importing sys will not raise an ImportError. fail_loader = _(['sys']) sys.meta_path.append(fail_loader) # Demonstrate that reloading doesn't work if the module is already in the # cache. reload(y) assert y._loaded_with == 'sys' assert y.sys # Now we remove sys from the modules cache, and try again. del sys.modules['sys'] reload(y) assert y._loaded_with == 'os' assert y.sys assert y.os # Now we remove the handles to the old y so it can get garbage-collected. del sys.modules['y'] del y import y assert y._loaded_with == 'os' try: assert y.sys except AttributeError: pass assert y.os </code></pre>
 

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