How do I retain source lines in tracebacks when running dynamically-compiled code objects?
<p>Say I use <a href="https://docs.python.org/2/library/functions.html#compile" rel="nofollow">compile</a> to create a <code>code</code> object from a string and a name:</p>

<pre><code>&gt;&gt;&gt; a = compile('raise ValueError\n', '&lt;at runtime&gt;', 'exec')
</code></pre>

<p>I would like the lines within that string to appear within the traceback (note - the following is run in IDLE):</p>

<pre><code>&gt;&gt;&gt; exec(a)
Traceback (most recent call last):
 File "&lt;pyshell#11&gt;", line 1, in &lt;module&gt;
    exec(c)
  File "&lt;at runtime&gt;", line 1, in &lt;module&gt;
    raise ValueError   &lt;-- This line is what I want
ValueError
</code></pre>

<p>Alas, they do not:</p>

<pre><code>&gt;&gt;&gt; exec(a)
Traceback (most recent call last):
 File "&lt;pyshell#11&gt;", line 1, in &lt;module&gt;
    exec(c)
  File "&lt;at runtime&gt;", line 1, in &lt;module&gt;
ValueError
</code></pre>

<p>Without creating a temporary file, how do I make that <code>raise ValueError</code> line appear in the traceback?</p>

<p>Using the undocumented <code>cache</code> member of the builtin <a href="https://docs.python.org/2/library/linecache.html" rel="nofollow"><code>linecache</code></a>, this seems to work:</p>

<pre><code>def better_compile(src, name, mode):
    # there is an example of this being set at
    # https://hg.python.org/cpython/file/2.7/Lib/linecache.py#l104
    from linecache import cache
    cache[name] = (
        len(src), None,
        [line+'\n' for line in src.splitlines()], name
    )
    return compile(src, name, mode)
</code></pre>



<pre><code>&gt;&gt;&gt; c = better_compile('raise ValueError\n', '&lt;a name&gt;', 'exec')
&gt;&gt;&gt; exec(c)
Traceback (most recent call last):
  File "&lt;pyshell#50&gt;", line 1, in &lt;module&gt;
    exec(c)
  File "&lt;a name&gt;", line 1, in &lt;module&gt;
    raise ValueError
ValueError
</code></pre>

<hr>

<p>It turns out this is <a href="https://github.com/python/cpython/blob/4b2d53def9de6034956efe64afff80df360ff1ac/Lib/idlelib/pyshell.py#L681" rel="nofollow">pretty much how IDLE does it</a></p>

python