9

在我的 python 程序中将文件上传到互联网,我使用 GTK 进度条来显示上传进度。但我面临的问题是进度条在上传完成之前不显示任何活动,然后它突然指示上传完成。我使用 pycurl 发出 http 请求...我的问题是 - 我是否需要一个多线程应用程序来上传文件并同时更新 gui?还是我犯了其他错误?

提前致谢!

4

5 回答 5

13

我将引用PyGTK 常见问题解答

您已经在窗口中创建了一个进度条,然后您开始运行一个循环来完成一些工作:

while work_left:
    ...do something...
    progressbar.set_fraction(...)

您会注意到该窗口甚至没有显示,或者如果显示,进度条将保持冻结状态,直到任务结束。解释很简单:gtk 是事件驱动的,您正在从 gtk 主循环中窃取控制权,从而阻止它处理正常的 GUI 更新事件。

最简单的解决方案是在每次进度更改时暂时将控制权交还给 gtk:

while work_left:
    ...do something...
    progressbar.set_fraction(...)
    while gtk.events_pending():
        gtk.main_iteration()

请注意,使用此解决方案,用户无法退出应用程序(gtk.main_quit 由于新循环 [gtk.main_iteration()] 而无法工作),直到您完成了重载工作。

另一种解决方案是使用 gtk 空闲函数,当 gtk 主循环无事可做时,它会调用这些函数。因此,gtk 处于控制之中,idle 函数必须做一些工作。如果还有更多工作要做,它应该返回 True,否则返回 False。

James Henstridge 指出了最好的解决方案(它没有缺点)。它利用python的生成器作为空闲函数,让python自动为我们保存状态。它是这样的:

def my_task(data):
    ...some work...
    while heavy_work_needed:
        ...do heavy work here...
        progress_label.set_text(data) # here we update parts of UI
        # there's more work, return True
        yield True
    # no more work, return False
    yield False

def on_start_my_task_button_click(data):
    task = my_task(data)
    gobject.idle_add(task.next)

上面的“while”只是一个例子。唯一的规则是它应该在做一些工作之后产生 True 并且还有更多工作要做,并且它必须在任务完成时产生 False。

于 2009-01-30T21:26:52.090 回答
1

问题很可能是在您的进度回调中,我认为您正在更新进度条,您没有调用手动更新显示,即通过 GUI 的事件循环运行。不过,这只是推测,如果您可以提供更多代码,则进一步缩小范围可能会更容易。

您需要手动更新显示的原因是因为您的主线程也在执行上传,这是它阻塞的地方。

于 2009-01-30T19:57:36.077 回答
0

在 python 2.x 中,整数操作数导致整数除法。试试这个:

#Callback function invoked when download/upload has progress
def progress(download_t, download_d, upload_t, upload_d):
    print 'in fileupload progress'
    mainwin.mainw.prog_bar.set_fraction(float(upload_d) / upload_t)
于 2009-01-30T21:15:17.857 回答
0

是的,您可能需要并发,是的,线程是一种方法,但如果您确实使用线程,请使用这样的方法: http: //unpythonic.blogspot.com/2007/08/using-threads-in-pygtk .html将消除痛苦,让您专注于重要方面。

(我没有因为懒惰而重复该博客文章中的所有内容,因此社区维基)。

于 2009-02-03T02:51:56.707 回答
0

如果您没有与 pycurl 结婚,一种选择是使用 GObject 的 IO 观察程序。

http://pygtk.org/pygtk2reference/gobject-functions.html#function-gobject--io-add-watch

使用它,您可以将文件上传与正常的 PyGTK 事件循环交错,甚至在您的 IO 监视回调中执行 set_progress 调用。如果您正在卸载所有上传到 pycurl 的工作,这实际上是不可行的,但如果您只是通过 HTTP 上传文件,io_add_watch 也会使使用套接字的痛苦少得多。

于 2009-03-19T05:00:58.070 回答