Proposal for adding Shallow Threads and a Main Loop to Python

Gary D. Duzan gduzan at bbn.com
Thu Mar 17 18:20:08 EST 2005


In article <1111097016.706850.281720 at o13g2000cwo.googlegroups.com>,
Rhamphoryncus <rhamph at gmail.com> wrote:
>
>import mainloop, urllib
>
>def get_and_save(path):
>    infile = waitfor urllib.urlopen(path, async=True)
>    outfile = waitfor open(path.split('/')[-1], async=True)
>    waitfor outfile.write(waitfor infile.read(async=True), async=True)
>    infile.close()
>    outfile.close()
>
>def main():
>    a = get_and_save("http://python.org/pics/PyBanner021.gif")
>    b = get_and_save("http://python.org/pics/pythonHi.gif")
>    c = get_and_save("http://python.org/pics/PythonPoweredSmall.gif")
>
>    waitfor allDone(a, b, c)
>
>if __name__ == "__main__":
>    mainloop.runUntil(main())
>
>Well there you have it.  I've glossed over many details but they can be
>cleared up later.  What I need to know now is how everybody else thinks
>about it.  Is this something you would use?  Does it seem like the
>right way to do it?  And of course the all important one, can I get it
>in to python core?  <0.5 wink>

   A while back I tossed something together to deal with the same issue
in terms of "futures" (or "promises".)  Here is roughly what the above
code would look like with futures as I implemented them:

###########################################################################
import urllib
from future import future

def get_and_save(path):
    infile = future(urllib.urlopen, path)
    outfile = future(open, path.split('/')[-1])

    def save(infile, outfile):
	outfile().write(infile().read())
	infile().close()
	outfile().close()

    return future(save, infile, outfile)

def main():
    a = get_and_save("http://python.org/pics/PyBanner021.gif")
    b = get_and_save("http://python.org/pics/pythonHi.gif")
    c = get_and_save("http://python.org/pics/PythonPoweredSmall.gif")

    a(), b(), c()

if __name__ == "__main__":
    main()
###########################################################################

   The future object initializer always returns immediately, and
the resulting "future" object can be passed around like any other
object. The __call__ method on the future object is used to get
the actual value. (I'm sure this could be avoided these days with
some sort of metaclass magic, but I haven't explored metaclasses
yet.)  If the value is ready, it is returned immediately; otherwise,
the accessor's thread is blocked until it is made ready, and then
the value is returned (or the appropriate exception is raised.)
Specifying a callable (and optional parameters) in the initializer
causes resolver threads to be fired off, and the result of the
callable's evaluation in the thread becomes the future's value. If
you don't specify anything, you can arrange to resolve the value
some other way. (This is useful if the value is provided by some
asynchronous mechanism.)

   This was all done using plain Python 1.5.2 in 80 lines of code,
including some blank lines and doc strings. Maybe I'll brush off
the code a bit and post it one of these days.

					Gary Duzan
					BBN Technologies





More information about the Python-list mailing list