Dan*_*nka 74 python multithreading
我有一个Python脚本,有时会向用户显示图像.图像有时可能非常大,并且经常被重复使用.显示它们并不重要,但显示与它们相关的消息是.我有一个功能,可以下载所需的图像并将其保存在本地.现在,它与向用户显示消息的代码内联运行,但对于非本地映像,有时可能需要10秒以上.有没有办法可以在需要时调用此函数,但在代码继续执行时在后台运行它?我会使用默认图像,直到正确的图像可用.
Tor*_*ler 106
做这样的事情:
def function_that_downloads(my_args):
# do some long download here
Run Code Online (Sandbox Code Playgroud)
然后内联,做这样的事情:
import threading
def my_inline_function(some_args):
# do some stuff
download_thread = threading.Thread(target=function_that_downloads, args=some_args)
download_thread.start()
# continue doing stuff
Run Code Online (Sandbox Code Playgroud)
您可能想要检查线程是否已完成,然后再通过调用继续执行其他操作 download_thread.isAlive()
通常,执行此操作的方法是使用线程池并排队下载,这将发出任务已完成处理的信号(即事件).您可以在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()
Run Code Online (Sandbox Code Playgroud)
不像我上面那样进行民意调查可能是有意义的.在这种情况下,我会将代码更改为:
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
Run Code Online (Sandbox Code Playgroud)
请注意,此处未设置守护程序标志.
我更喜欢使用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()
Run Code Online (Sandbox Code Playgroud)
一切都在一个线程中运行,但每当内核操作阻塞时,gevent 就会在有其他“greenlet”运行时切换上下文。关于锁定等的担忧大大减少,因为一次只有一件事在运行,但只要在“主”上下文中执行阻塞操作,图像就会继续下载。
根据您想要在后台执行的操作量和类型,这可能比基于线程的解决方案更好或更差;当然,它更具可扩展性(即您可以在后台做更多事情),但在当前情况下这可能不是问题。
| 归档时间: |
|
| 查看次数: |
63992 次 |
| 最近记录: |