Python中的后台function

我有一个Python脚本,有时会向用户显示图像。 图像有时可能很大,经常重复使用。 显示它们并不重要,但显示与它们相关的消息是。 我有一个function,下载所需的图像,并保存在本地。 现在,它与向用户显示消息的代码内联运行,但对于非本地图像,有时可能需要超过10秒。 有什么办法可以在需要的时候调用这个函数,但是在代码继续执行的时候在后台运行它? 我只是使用默认的图像,直到正确的一个可用。

做这样的事情:

def function_that_downloads(my_args): # do some long download here 

然后内联,做这样的事情:

 import threading def my_inline_function(some_args): #do some stuff download_thread = threading.Thread(target=function_that_downloads, args=my_args) download_thread.start() #continue doing stuff 

您可能要通过调用download_thread.isAlive()来检查线程是否完成之后,

通常情况下,这样做的方式是使用线程池和排队下载,这将发出一个信号,即事件,该任务已完成处理。 您可以在Python提供的线程模块的范围内执行此操作。

要执行上述操作,我将使用事件对象和队列模块 。

但是,使用简单的threading.Thread可以做一个快速和肮脏的演示。 threading.Thread实现可以在下面看到:

 import os import threading import time import urllib2 class ImageDownloader(threading.Thread): def __init__(self, function_that_downloads): threading.Thread.__init__(self) self.runnable = function_that_downloads self.daemon = True def run(self): self.runnable() def downloads(): with open('somefile.html', 'w+') as f: try: f.write(urllib2.urlopen('http://google.com').read()) except urllib2.HTTPError: f.write('sorry no dice') print 'hi there user' print 'how are you today?' thread = ImageDownloader(downloads) thread.start() while not os.path.exists('somefile.html'): print 'i am executing but the thread has started to download' time.sleep(1) print 'look ma, thread is not alive: ', thread.is_alive() 

这可能是有道理的,而不是像我在上面做的那样轮询。 在这种情况下,我会将代码更改为:

 import os import threading import time import urllib2 class ImageDownloader(threading.Thread): def __init__(self, function_that_downloads): threading.Thread.__init__(self) self.runnable = function_that_downloads def run(self): self.runnable() def downloads(): with open('somefile.html', 'w+') as f: try: f.write(urllib2.urlopen('http://google.com').read()) except urllib2.HTTPError: f.write('sorry no dice') print 'hi there user' print 'how are you today?' thread = ImageDownloader(downloads) thread.start() # show message thread.join() # display image 

注意这里没有设置守护进程标志。

我更喜欢用gevent来做这样的事情:

 import gevent from gevent import monkey; monkey.patch_all() greenlet = gevent.spawn( function_to_download_image ) display_message() # ... perhaps interaction with the user here # this will wait for the operation to complete (optional) greenlet.join() # alternatively if the image display is no longer important, this will abort it: #greenlet.kill() 

所有东西都在一个线程中运行,但是当内核操作阻塞时,gevent会在有其他“greenlet”运行时切换上下文。 对locking等等的担心大大减less了,因为一次只能运行一个东西,但是只要在“main”上下文中执行阻塞操作,映像就会继续下载。

取决于你想在后台做多less,以及想要做什么样的事情,这可能比基于线程的解决scheme更好或更差。 当然,这是可扩展的(也就是说,你可以在后台做更多的事情),但是在目前的情况下,这可能不是问题。