Dav*_*lla 16 python gtk application-development pygi
我正在编写一个 Python + GObject 应用程序,它需要在启动时从磁盘读取大量数据。数据是同步读取的,大约需要10秒才能完成读取操作,在此期间UI的加载会有延迟。
我想异步运行任务,并在它准备好时收到通知,而不会阻塞 UI,或多或少像:
def take_ages():
read_a_huge_file_from_disk()
def on_finished_long_task():
print "Finished!"
run_long_task(task=take_ages, callback=on_finished_long_task)
load_the_UI_without_blocking_on_long_task()
Run Code Online (Sandbox Code Playgroud)
我过去曾将GTask用于此类事情,但我担心它的代码已经 3 年没有被触及,更不用说移植到 GObject Introspection 了。最重要的是,它在 Ubuntu 12.04 中不再可用。所以我正在寻找一种简单的方法来异步运行任务,无论是标准 Python 方式还是 GObject/GTK+ 标准方式。
编辑:这是一些代码,其中包含我正在尝试执行的操作的示例。我已经python-defer按照评论中的建议进行了尝试,但是我无法异步运行长任务并让 UI 加载而不必等待它完成。浏览测试代码。
是否有一种简单且广泛使用的方式来运行异步任务并在它们完成时得到通知?
xub*_*tix 15
您的问题很常见,因此有很多解决方案(棚、多处理或线程队列、工作池……)
由于它是如此常见,因此还有一个名为 concurrent.futures的 Python 内置解决方案(在 3.2 中,但在此处反向移植:http : //pypi.python.org/pypi/futures)。'Futures' 有多种语言版本,因此 python 对它们的称呼相同。这是典型的调用(这是您的完整示例,但是,db 部分被 sleep 替换,请参阅下面的原因)。
from concurrent import futures
executor = futures.ProcessPoolExecutor(max_workers=1)
#executor = futures.ThreadPoolExecutor(max_workers=1)
future = executor.submit(slow_load)
future.add_done_callback(self.on_complete)
Run Code Online (Sandbox Code Playgroud)
现在解决您的问题,这比您的简单示例所建议的要复杂得多。一般来说,你有线程或进程来解决这个问题,但这就是你的例子如此复杂的原因:
slow_load从数据库返回的对象是不可pickelable的,这意味着它们不能简单地在进程之间传递。所以:没有软件中心结果的多重处理!print,没有 gtk 状态改变,除了添加回调!threads_init,如果您调用 gtk 或类似方法,则必须保护该方法(在早期版本中,这是gtk.gdk.threads_enter(), gtk.gdk.threads_leave(). 参见 gstreamer:http : //pygstdocs.berlios.de/pygst-tutorial/playbin。 html)。我可以给你以下建议:
slow_load的返回pickelable结果并使用带有流程的期货。作为一个说明:由别人给出的解决方案(Gio.io_scheduler_push_job,async_call)做与工作time.sleep,但不是softwarecenter.db。这是因为这一切都归结为线程或进程和线程不能与 gtk 和softwarecenter.
Sie*_*ter 10
这是使用 GIO 的 I/O 调度程序的另一个选项(我以前从未在 Python 中使用过它,但下面的示例似乎运行良好)。
from gi.repository import GLib, Gio, GObject
import time
def slow_stuff(job, cancellable, user_data):
print "Slow!"
for i in xrange(5):
print "doing slow stuff..."
time.sleep(0.5)
print "finished doing slow stuff!"
return False # job completed
def main():
GObject.threads_init()
print "Starting..."
Gio.io_scheduler_push_job(slow_stuff, None, GLib.PRIORITY_DEFAULT, None)
print "It's running async..."
GLib.idle_add(ui_stuff)
GLib.MainLoop().run()
def ui_stuff():
print "This is the UI doing stuff..."
time.sleep(1)
return True
if __name__ == '__main__':
main()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15536 次 |
| 最近记录: |