操作过程中进度条不更新

发布于 2024-07-12 04:04:26 字数 189 浏览 5 评论 0原文

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

提前致谢!

in my python program to upload a file to the internet, im using a GTK progress bar to show the upload progress. But the problems that im facing is that the progress bar does not show any activity until the upload is complete, and then it abruptly indicates upload complete. im using pycurl to make the http requests...my question is -
do i need to have a multi-threaded application to upload the file and simultaneously update the gui? or is there some other mistake that im making?

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

盛装女皇 2024-07-19 04:04:26

我将引用 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_iteration()],gtk.main_quit 将不起作用)。

另一个解决方案是使用 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。

I'm going to quote the PyGTK FAQ:

You have created a progress bar inside a window, then you start running a loop that does some work:

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

You will notice that the window doesn't even show up, or if it does the progress bar stays frozen until the end of the task. The explanation is simple: gtk is event driven, and you are stealing control away from the gtk main loop, thus preventing it from processing normal GUI update events.

The simplest solution consists on temporarily giving control back to gtk every time the progress is changed:

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

Notice that with this solution, the user cannot quit the application (gtk.main_quit would not work because of new loop [gtk.main_iteration()]) until your heavy_work is done.

Another solution consists on using gtk idle functions, which are called by the gtk main loop whenever it has nothing to do. Therefore, gtk is in control, and the idle function has to do a bit of work. It should return True if there's more work to be done, otherwise False.

The best solution (it has no drawbacks) was pointed out by James Henstridge. It is taking advantage of python's generators as idle functions, to make python automatically preserve the state for us. It goes like this:

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)

The 'while' above is just an example. The only rules are that it should yield True after doing a bit of work and there's more work to do, and it must yield False when the task is done.

独﹏钓一江月 2024-07-19 04:04:26

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

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

More than likely the issue is that in your progress callback, which is where I presume you're updating the progress bar, you're not making a call to manually update the display i.e. run through the GUI's event loop. This is just speculation though, if you can provide more code, it might be easier to narrow it down further.

The reason you need to manually update the display is because your main thread is also performing the upload, which is where it's blocking.

抱猫软卧 2024-07-19 04:04:26

在 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)

In python 2.x integer operands result in integer division. Try this:

#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)
清风不识月 2024-07-19 04:04:26

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

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

Yes, you probably need concurrency, and yes threads are one approach, but if you do use threads, please use an method like this one: http://unpythonic.blogspot.com/2007/08/using-threads-in-pygtk.html which will abstract away the pain, and allow you to focus on the important aspects.

(I have not repeated everything in that blog post through laziness, hence community wiki).

只是偏爱你 2024-07-19 04:04:26

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

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

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

One option, if you are not married to pycurl, is to use GObject's IO watchers.

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

Using this you can interleave the file upload with the normal PyGTK event loop, and even do the set_progress call in your IO watch callback. If you are offloading all the work for uploading onto pycurl this is not really feasible, but if you're just uploading a file over HTTP, io_add_watch will make using a socket for this much less painful as well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文