Saya punya skrip Python yang terkadang menampilkan gambar kepada pengguna. Gambar bisa, kadang-kadang, menjadi cukup besar, dan sering digunakan kembali. Menampilkannya tidak penting, tetapi menampilkan pesan yang terkait dengannya. Saya punya fungsi yang mengunduh gambar yang dibutuhkan dan menyimpannya secara lokal. Saat ini dijalankan sesuai dengan kode yang menampilkan pesan kepada pengguna, tetapi terkadang membutuhkan waktu lebih dari 10 detik untuk gambar non-lokal. Adakah cara saya dapat memanggil fungsi ini saat diperlukan, tetapi menjalankannya di latar belakang sementara kode terus dijalankan? Saya hanya akan menggunakan gambar default sampai gambar yang benar tersedia.
sumber
import threading, time; wait=lambda: time.sleep(2); t=threading.Thread(target=wait); t.start(); print('end')
). Saya berharap "latar belakang" tersirat terlepas juga.subprocess
ataumultiprocessing
python.add(a,b)
dan mendapatkan nilaiBiasanya cara untuk melakukan ini adalah dengan menggunakan kumpulan utas dan unduhan antrian yang akan mengeluarkan sinyal, alias peristiwa, ketika tugas itu telah selesai diproses. Anda dapat melakukan ini dalam cakupan modul penguliran yang disediakan Python.
Untuk melakukan tindakan tersebut, saya akan menggunakan objek acara dan modul Antrian .
Namun, demonstrasi cepat dan kotor tentang apa yang dapat Anda lakukan dengan
threading.Thread
penerapan sederhana dapat dilihat di bawah ini: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()
Mungkin masuk akal untuk tidak melakukan jajak pendapat seperti yang saya lakukan di atas. Dalam hal ini, saya akan mengubah kodenya menjadi ini:
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
Perhatikan bahwa tidak ada tanda daemon yang disetel di sini.
sumber
Saya lebih suka menggunakan gevent untuk hal semacam ini:
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()
Semuanya berjalan dalam satu thread, tetapi setiap kali operasi kernel memblokir, gevent mengganti konteks saat ada "greenlets" lain yang berjalan. Kekhawatiran tentang penguncian, dll. Jauh berkurang, karena hanya ada satu hal yang berjalan pada satu waktu, namun gambar akan terus diunduh setiap kali operasi pemblokiran dijalankan dalam konteks "utama".
Bergantung pada seberapa banyak, dan hal apa yang ingin Anda lakukan di latar belakang, ini bisa lebih baik atau lebih buruk daripada solusi berbasis threading; tentu saja, ini jauh lebih berskala (yaitu, Anda dapat melakukan lebih banyak hal di latar belakang), tetapi itu mungkin tidak menjadi perhatian dalam situasi saat ini.
sumber
from gevent import monkey; monkey.patch_all()
?