<!DOCTYPE html><html><head>
<style type="text/css">body { font-family:'Times New Roman'; font-size:13px}</style>
</head>
<body>On Mon, 02 Jul 2012 19:31:14 -0500, Dan Stromberg &lt;drsalists@gmail.com&gt; wrote:<br><br><blockquote style="margin: 0 0 0.80ex; border-left: #0000FF 2px solid; padding-left: 1ex"><br><div class="gmail_quote">On Thu, Jun 28, 2012 at 9:40 PM, Dan Stromberg <span dir="ltr">&lt;<a href="mailto:drsalists@gmail.com" target="_blank">drsalists@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div style="margin-left:40px"><br></div>Hi.<br><br>I'm a Twisted neophyte, but I've been using Python a long time.<br><br>My question:<br>
<div style="margin-left:40px">Is there a way of producing a deferred 
graph in a Python program at a given point in time? &nbsp;Perhaps something 
based on graphviz and objgraph.py? &nbsp;We're able to detect when we're 
having the problem, we just don't (yet) know its cause.<br>
</div>
<br><br>Background:<br><div style="margin-left:40px">I'm looking at some code with a bit over 200 addCallback/addErrback/addCallbacks in it.<br><br>It's got a problem where sometimes the deferreds seem to just stop executing. &nbsp;I see in the doc it says that this can happen if you've neglected to add an errback to the end of one or more of your deferred chains.<br>

<br>One of the people who's been here longer than me, indicated that he's gone through the code looking for such issues, and didn't find any. &nbsp;This suggests to me that either there's some other cause, or that it really is a deferred without a final errback, but it's hidden in a dark corner of the code somewhere.<br>

</div><br><br>Thanks!<br><br>
</blockquote></div>I put together something to do a single-point-in-time graph (as distorted/delayed by the time it takes to go through all the objects in the python interpreter) of deferreds.&nbsp; Please find it below as a shar archive (wow, someone still does those?&nbsp;&nbsp; Yeah, sometimes)</blockquote><div><br></div><div>Cool stuff - but could you use an ordinary archive format? Asking the whole mailing list to run gobs of shell code is.... I dunno. not something I'm going to bother with even if I would like to.</div><div><br></div><div>-E</div><div><br></div><div><br></div><blockquote style="margin: 0 0 0.80ex; border-left: #0000FF 2px solid; padding-left: 1ex">&nbsp; Anyway, given a tree of deferreds, this will produce a whatever.dot file, which can be fed to graphviz' "dot -Tpdf whatever.dot &gt; whatever.pdf", and the pdf has a rather nice-looking graph of the deferreds.<br>
<br>#!/bin/sh<br># This is a shell archive (produced by GNU sharutils 4.11.1).<br># To extract the files from this archive, save it to some FILE, remove<br># everything before the `#!/bin/sh' line above, then type `sh FILE'.<br>
#<br>lock_dir=_sh32156<br># Made on 2012-07-02 21:48 UTC by &lt;stromberg@aw50&gt;.<br># Source directory was `/home/stromberg/src/twisted-experiments'.<br>#<br># Existing files will *not* be overwritten, unless `-c' is specified.<br>
#<br># This shar contains:<br># length mode&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name<br># ------ ---------- ------------------------------------------<br>#&nbsp;&nbsp; 2181 -rwxr-xr-x deferreddump.py<br>#&nbsp;&nbsp; 3174 -rwxr-xr-x wedgedump<br>#<br>MD5SUM=${MD5SUM-md5sum}<br>
f=`${MD5SUM} --version | egrep '^md5sum .*(core|text)utils'`<br>test -n "${f}" &amp;&amp; md5check=true || md5check=false<br>${md5check} || \<br>&nbsp; echo 'Note: not verifying md5sums.&nbsp; Consider installing GNU coreutils.'<br>
if test "X$1" = "X-c"<br>then keep_file=''<br>else keep_file=true<br>fi<br>echo=echo<br>save_IFS="${IFS}"<br>IFS="${IFS}:"<br>gettext_dir=<br>locale_dir=<br>set_echo=false<br>
<br>for dir in $PATH<br>do<br>&nbsp; if test -f $dir/gettext \<br>&nbsp;&nbsp;&nbsp;&nbsp; &amp;&amp; ($dir/gettext --version &gt;/dev/null 2&gt;&amp;1)<br>&nbsp; then<br>&nbsp;&nbsp;&nbsp; case `$dir/gettext --version 2&gt;&amp;1 | sed 1q` in<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *GNU*) gettext_dir=$dir<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set_echo=true<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break ;;<br>&nbsp;&nbsp;&nbsp; esac<br>&nbsp; fi<br>done<br><br>if ${set_echo}<br>then<br>&nbsp; set_echo=false<br>&nbsp; for dir in $PATH<br>&nbsp; do<br>&nbsp;&nbsp;&nbsp; if test -f $dir/shar \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;&amp; ($dir/shar --print-text-domain-dir &gt;/dev/null 2&gt;&amp;1)<br>
&nbsp;&nbsp;&nbsp; then<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; locale_dir=`$dir/shar --print-text-domain-dir`<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set_echo=true<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break<br>&nbsp;&nbsp;&nbsp; fi<br>&nbsp; done<br><br>&nbsp; if ${set_echo}<br>&nbsp; then<br>&nbsp;&nbsp;&nbsp; TEXTDOMAINDIR=$locale_dir<br>&nbsp;&nbsp;&nbsp; export TEXTDOMAINDIR<br>
&nbsp;&nbsp;&nbsp; TEXTDOMAIN=sharutils<br>&nbsp;&nbsp;&nbsp; export TEXTDOMAIN<br>&nbsp;&nbsp;&nbsp; echo="$gettext_dir/gettext -s"<br>&nbsp; fi<br>fi<br>IFS="$save_IFS"<br>if (echo "testing\c"; echo 1,2,3) | grep c &gt;/dev/null<br>then if (echo -n test; echo 1,2,3) | grep n &gt;/dev/null<br>
&nbsp;&nbsp;&nbsp;&nbsp; then shar_n= shar_c='<br>'<br>&nbsp;&nbsp;&nbsp;&nbsp; else shar_n=-n shar_c= ; fi<br>else shar_n= shar_c='\c' ; fi<br>f=shar-touch.$$<br>st1=200112312359.59<br>st2=123123592001.59<br>st2tr=123123592001.5 # old SysV 14-char limit<br>
st3=1231235901<br><br>if touch -am -t ${st1} ${f} &gt;/dev/null 2&gt;&amp;1 &amp;&amp; \<br>&nbsp;&nbsp; test ! -f ${st1} &amp;&amp; test -f ${f}; then<br>&nbsp; shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'<br><br>elif touch -am ${st2} ${f} &gt;/dev/null 2&gt;&amp;1 &amp;&amp; \<br>
&nbsp;&nbsp; test ! -f ${st2} &amp;&amp; test ! -f ${st2tr} &amp;&amp; test -f ${f}; then<br>&nbsp; shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'<br><br>elif touch -am ${st3} ${f} &gt;/dev/null 2&gt;&amp;1 &amp;&amp; \<br>
&nbsp;&nbsp; test ! -f ${st3} &amp;&amp; test -f ${f}; then<br>&nbsp; shar_touch='touch -am $3$4$5$6$2 "$8"'<br><br>else<br>&nbsp; shar_touch=:<br>&nbsp; echo<br>&nbsp; ${echo} 'WARNING: not restoring timestamps.&nbsp; Consider getting and<br>
installing GNU `touch'\'', distributed in GNU coreutils...'<br>&nbsp; echo<br>fi<br>rm -f ${st1} ${st2} ${st2tr} ${st3} ${f}<br>#<br>if test ! -d ${lock_dir} ; then :<br>else ${echo} "lock directory ${lock_dir} exists"<br>
&nbsp;&nbsp;&nbsp;&nbsp; exit 1<br>fi<br>if mkdir ${lock_dir}<br>then ${echo} "x - created lock directory ${lock_dir}."<br>else ${echo} "x - failed to create lock directory ${lock_dir}."<br>&nbsp;&nbsp;&nbsp;&nbsp; exit 1<br>fi<br># ============= deferreddump.py ==============<br>
if test -n "${keep_file}" &amp;&amp; test -f 'deferreddump.py'<br>then<br>${echo} "x - SKIPPING deferreddump.py (file already exists)"<br>else<br>${echo} "x - extracting deferreddump.py (text)"<br>
&nbsp; sed 's/^X//' &lt;&lt; 'SHAR_EOF' &gt; 'deferreddump.py' &amp;&amp;<br>#!/usr/bin/python<br>X<br># See also: <a href="http://twistedmatrix.com/trac/ticket/3858">http://twistedmatrix.com/trac/ticket/3858</a><br>
# and:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="http://twistedmatrix.com/trac/ticket/1402">http://twistedmatrix.com/trac/ticket/1402</a><br># and:<br>#&nbsp;&nbsp; twisted.internet.defer also exposes a setDebugging(bool) function to<br>#&nbsp;&nbsp; store call stacks from creation and invocation in deferred objects,<br>
#&nbsp;&nbsp; it's what I was using to try and figure out what was going on, but<br>#&nbsp;&nbsp; it's not nearly as at-a-glance as a graph is.<br>X<br>import gc<br>import sys<br>X<br>import twisted.internet.defer<br>X<br>def escape(callback_type, obj):<br>
X&nbsp;&nbsp;&nbsp; dummy = callback_type<br>X&nbsp;&nbsp;&nbsp; return '%s' % (str(obj).replace(' ', '_').replace(':', '').replace('&lt;', '').replace('&gt;', ''), )<br>X<br>def dump(outfile = sys.stdout):<br>
X&nbsp;&nbsp;&nbsp; outfile.write('digraph deferred_digraph {\n')<br>X&nbsp;&nbsp;&nbsp; for obj in gc.get_objects():<br>X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if isinstance(obj, twisted.internet.defer.Deferred):<br>X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; len_callbacks = len(obj.callbacks)<br>X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if obj.callbacks:<br>
X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outfile.write('\t%s -&gt; %s\n' % (escape('', obj), escape('', obj.callbacks[0][0][0])))<br>X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outfile.write('\t%s -&gt; %s\n' % (escape('', obj), escape('', obj.callbacks[0][1][0])))<br>
X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for callbackpairno in range(len_callbacks - 1):<br>X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; current_callback = obj.callbacks[callbackpairno][0]<br>X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; current_errback = obj.callbacks[callbackpairno][1]<br>X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; current_callback_desc = current_callback[0]<br>
X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; current_errback_desc = current_errback[0]<br>X<br>X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; next_callback = obj.callbacks[callbackpairno + 1][0]<br>X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; next_errback = obj.callbacks[callbackpairno + 1][1]<br>X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; next_callback_desc = next_callback[0]<br>
X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; next_errback_desc = next_errback[0]<br>X<br>X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outfile.write('\t%s -&gt; %s;\n' % (escape('callback', current_callback_desc), escape('callback', next_callback_desc)))<br>
X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outfile.write('\t%s -&gt; %s;\n' % (escape('errback', current_errback_desc), escape('errback', next_errback_desc)))<br>X<br>X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outfile.write('\t%s -&gt; %s;\n' % (escape('callback', current_callback_desc), escape('errback', next_errback_desc)))<br>
X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outfile.write('\t%s -&gt; %s;\n' % (escape('errback', current_errback_desc), escape('callback', next_callback_desc)))<br>X<br>X&nbsp;&nbsp;&nbsp; outfile.write('}\n')<br>X<br>X<br>SHAR_EOF<br>
&nbsp; (set 20 12 06 29 18 02 00 'deferreddump.py'<br>&nbsp;&nbsp; eval "${shar_touch}") &amp;&amp; \<br>&nbsp; chmod 0755 'deferreddump.py'<br>if test $? -ne 0<br>then ${echo} "restore of deferreddump.py failed"<br>
fi<br>&nbsp; if ${md5check}<br>&nbsp; then (<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ${MD5SUM} -c &gt;/dev/null 2&gt;&amp;1 || ${echo} 'deferreddump.py': 'MD5 check failed'<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ) &lt;&lt; \SHAR_EOF<br>45b2aed37cc2e57bc58f46a42eb2a2d4&nbsp; deferreddump.py<br>
SHAR_EOF<br>&nbsp; else<br>test `LC_ALL=C wc -c &lt; 'deferreddump.py'` -ne 2181 &amp;&amp; \<br>&nbsp; ${echo} "restoration warning:&nbsp; size of 'deferreddump.py' is not 2181"<br>&nbsp; fi<br>fi<br># ============= wedgedump ==============<br>
if test -n "${keep_file}" &amp;&amp; test -f 'wedgedump'<br>then<br>${echo} "x - SKIPPING wedgedump (file already exists)"<br>else<br>${echo} "x - extracting wedgedump (text)"<br>&nbsp; sed 's/^X//' &lt;&lt; 'SHAR_EOF' &gt; 'wedgedump' &amp;&amp;<br>
#!/usr/bin/python<br>X<br># Unhandled Errors<br>X<br># From <a href="http://twistedmatrix.com/documents/current/core/howto/defer.html">http://twistedmatrix.com/documents/current/core/howto/defer.html</a> :<br>X<br>#&nbsp;&nbsp; If a Deferred is garbage-collected with an unhandled error (i.e. it<br>
#&nbsp;&nbsp; would call the next errback if there was one), then Twisted will write<br>#&nbsp;&nbsp; the error's traceback to the log file. This means that you can<br>#&nbsp;&nbsp; typically get away with not adding errbacks and still get errors<br>
#&nbsp;&nbsp; logged. Be careful though; if you keep a reference to the Deferred<br>#&nbsp;&nbsp; around, preventing it from being garbage-collected, then you may never<br>#&nbsp;&nbsp; see the error (and your callbacks will mysteriously seem to have never<br>
#&nbsp;&nbsp; been called). If unsure, you should explicitly add an errback after<br>#&nbsp;&nbsp; your callbacks, even if all you do is:<br>X<br>#&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # Make sure errors get logged<br>#&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; from twisted.python import log<br>#&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d.addErrback(log.err)<br>
X<br>import sys<br>#mport time<br>X<br>import twisted.internet.defer<br>import twisted.python<br>X<br>import deferreddump<br>X<br>def get_deferred():<br>X&nbsp;&nbsp;&nbsp; return twisted.internet.defer.succeed(1)<br>X<br>def cb1(value):<br>
X&nbsp;&nbsp;&nbsp; print value<br>X&nbsp;&nbsp;&nbsp; return value * 2<br>X<br>def cb2(value):<br>X&nbsp;&nbsp;&nbsp; #raise ValueError<br>X&nbsp;&nbsp;&nbsp; print value<br>X&nbsp;&nbsp;&nbsp; return value * 2<br>X<br>def cb3(value):<br>X&nbsp;&nbsp;&nbsp; print value<br>X&nbsp;&nbsp;&nbsp; return value * 2<br>X<br>def cb4(value):<br>
X&nbsp;&nbsp;&nbsp; print value<br>X&nbsp;&nbsp;&nbsp; return value * 2<br>X<br>def cb5(value):<br>X&nbsp;&nbsp;&nbsp; print value<br>X&nbsp;&nbsp;&nbsp; return value * 2<br>X<br>def cb6(value):<br>X&nbsp;&nbsp;&nbsp; print value<br>X&nbsp;&nbsp;&nbsp; return value * 2<br>X<br>def cb7(value):<br>X&nbsp;&nbsp;&nbsp; print value<br>
X&nbsp;&nbsp;&nbsp; return value * 2<br>X<br>def cb8(value):<br>X&nbsp;&nbsp;&nbsp; print value<br>X&nbsp;&nbsp;&nbsp; return value * 2<br>X<br>def eb1(value):<br>X&nbsp;&nbsp;&nbsp; twisted.python.log.err()<br>X<br>def eb2(value):<br>X&nbsp;&nbsp;&nbsp; twisted.python.log.err()<br>X<br>def eb3(value):<br>
X&nbsp;&nbsp;&nbsp; twisted.python.log.err()<br>X<br>def eb4(value):<br>X&nbsp;&nbsp;&nbsp; twisted.python.log.err()<br>X<br>def eb5(value):<br>X&nbsp;&nbsp;&nbsp; twisted.python.log.err()<br>X<br>def eb6(value):<br>X&nbsp;&nbsp;&nbsp; twisted.python.log.err()<br>X<br>def eb7(value):<br>
X&nbsp;&nbsp;&nbsp; twisted.python.log.err()<br>X<br>def eb8(value):<br>X&nbsp;&nbsp;&nbsp; twisted.python.log.err()<br>X<br>def arbitrary_function(add_final_log):<br>X&nbsp;&nbsp;&nbsp; deferred = get_deferred()<br>X<br>X&nbsp;&nbsp;&nbsp; # apparently we can use the same callback multiple times in the same deferred<br>
X&nbsp;&nbsp;&nbsp; first_deferred = deferred.addCallback(cb1)<br>X&nbsp;&nbsp;&nbsp; first_deferred.pause()<br>X&nbsp;&nbsp;&nbsp; deferred.addCallbacks(cb1, eb1)<br>X&nbsp;&nbsp;&nbsp; deferred.addCallbacks(cb2, eb2)<br>X&nbsp;&nbsp;&nbsp; deferred.addCallbacks(cb3, eb3)<br>X&nbsp;&nbsp;&nbsp; deferred.addCallbacks(cb4, eb4)<br>
X&nbsp;&nbsp;&nbsp; deferred.addCallbacks(cb5, eb5)<br>X&nbsp;&nbsp;&nbsp; deferred.addCallbacks(cb6, eb6)<br>X&nbsp;&nbsp;&nbsp; deferred.addCallbacks(cb7, eb7)<br>X<br>X&nbsp;&nbsp;&nbsp; with open('t.dot', 'w') as file_:<br>X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; deferreddump.dump(file_)<br>X<br>
X&nbsp;&nbsp;&nbsp; first_deferred.unpause()<br>X&nbsp;&nbsp;&nbsp; if add_final_log:<br>X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; deferred.addCallbacks(cb4, twisted.python.log.err)<br>X&nbsp;&nbsp;&nbsp; else:<br>X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; deferred.addCallback(cb4)<br>X<br>X&nbsp;&nbsp;&nbsp; return deferred<br>X<br>def usage(retval):<br>
X&nbsp;&nbsp;&nbsp; sys.stderr.write('Usage: %s --add-final-log\n' % sys.argv[0])<br>X&nbsp;&nbsp;&nbsp; sys.exit(retval)<br>X<br>def main():<br>X&nbsp;&nbsp;&nbsp; add_final_log = False<br>X&nbsp;&nbsp;&nbsp; while sys.argv[1:]:<br>X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if sys.argv[1] == '--add-final-log':<br>
X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; add_final_log = True<br>X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elif sys.argv[1] in [ '-h', '--help' ]:<br>X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; usage(0)<br>X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else:<br>X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sys.stderr.write('%s: Unrecognized option: %s\n' % (sys.argv[0], sys.argv[1]))<br>
X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; usage(1)<br>X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; del sys.argv[1]<br>X<br>X&nbsp;&nbsp;&nbsp; deferred = arbitrary_function(add_final_log)<br>X&nbsp;&nbsp;&nbsp; with open('/dev/null', 'w') as file_:<br>X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; file_.write(str(deferred))<br>X<br>X&nbsp;&nbsp;&nbsp; sys.exit(0)<br>
X<br>main()<br>X<br>SHAR_EOF<br>&nbsp; (set 20 12 07 02 21 46 02 'wedgedump'<br>&nbsp;&nbsp; eval "${shar_touch}") &amp;&amp; \<br>&nbsp; chmod 0755 'wedgedump'<br>if test $? -ne 0<br>then ${echo} "restore of wedgedump failed"<br>
fi<br>&nbsp; if ${md5check}<br>&nbsp; then (<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ${MD5SUM} -c &gt;/dev/null 2&gt;&amp;1 || ${echo} 'wedgedump': 'MD5 check failed'<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ) &lt;&lt; \SHAR_EOF<br>d526664fcf63762f768303af91a74a5f&nbsp; wedgedump<br>
SHAR_EOF<br>&nbsp; else<br>test `LC_ALL=C wc -c &lt; 'wedgedump'` -ne 3174 &amp;&amp; \<br>&nbsp; ${echo} "restoration warning:&nbsp; size of 'wedgedump' is not 3174"<br>&nbsp; fi<br>fi<br>if rm -fr ${lock_dir}<br>then ${echo} "x - removed lock directory ${lock_dir}."<br>
else ${echo} "x - failed to remove lock directory ${lock_dir}."<br>&nbsp;&nbsp;&nbsp;&nbsp; exit 1<br>fi<br>exit 0<br><br>
</blockquote><br><br><br><div id="M2Signature"><div>-- </div><div>Using Opera's revolutionary email client: <a href="http://www.opera.com/mail/">http://www.opera.com/mail/</a></div></div></body></html>