我有一个Python脚本,有时会向用户显示图像。这些图像有时可能很大,并且经常重复使用。显示它们并不重要,但是显示与它们关联的消息是至关重要的。我有一个功能,可以下载所需的图像并将其保存在本地。现在,它与向用户显示消息的代码内联运行,但是对于非本地图像,有时可能需要10秒钟以上。有没有一种方法可以在需要时调用此函数,但是在代码继续执行的同时在后台运行?我只会使用默认图像,直到正确的图像可用为止。
我有一个Python脚本,有时会向用户显示图像。这些图像有时可能很大,并且经常重复使用。显示它们并不重要,但是显示与它们关联的消息是至关重要的。我有一个功能,可以下载所需的图像并将其保存在本地。现在,它与向用户显示消息的代码内联运行,但是对于非本地图像,有时可能需要10秒钟以上。有没有一种方法可以在需要时调用此函数,但是在代码继续执行的同时在后台运行?我只会使用默认图像,直到正确的图像可用为止。
Answers:
做这样的事情:
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, name="Downloader", args=some_args)
download_thread.start()
# continue doing stuff
您可能需要在调用其他内容之前检查线程是否已完成 download_thread.isAlive()
subprocess
或multiprocessing
python模块。
add(a,b)
并获取该方法的返回值
通常,执行此操作的方法是使用线程池和队列下载,当任务完成处理时,它们将发出信号(又称为事件)。您可以在Python提供的线程模块范围内执行此操作。
但是,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”时切换上下文。由于一次只运行一件事,因此减少了对锁定等的担忧,但是只要在“主要”上下文中执行阻止操作,映像就将继续下载。
取决于您要在后台执行多少操作以及执行哪种操作,这可能比基于线程的解决方案更好或更糟。当然,它具有更大的可伸缩性(即,您可以在后台执行更多操作),但是在当前情况下这可能并不重要。
from gevent import monkey; monkey.patch_all()
什么?
import threading, time; wait=lambda: time.sleep(2); t=threading.Thread(target=wait); t.start(); print('end')
)。我希望“背景”也暗示超脱。