2009-01-30 43 views
8

trong chương trình python của tôi để tải tệp lên internet, sử dụng thanh tiến trình GTK để hiển thị tiến trình tải lên. Nhưng những vấn đề mà im phải đối mặt là thanh tiến trình không hiển thị bất kỳ hoạt động nào cho đến khi quá trình tải lên hoàn tất và sau đó đột ngột cho biết quá trình tải lên hoàn tất. im sử dụng pycurl để thực hiện các yêu cầu http ... câu hỏi của tôi là - tôi có cần phải có ứng dụng đa luồng để tải tệp lên và cập nhật đồng thời gui không? hoặc là có một số sai lầm khác mà im làm?Thanh tiến trình không cập nhật trong khi hoạt động

Cảm ơn trước!

Trả lời

12

Tôi sẽ trích dẫn PyGTK FAQ:

Bạn đã tạo một thanh tiến trình bên trong một cửa sổ, sau đó bạn bắt đầu chạy một vòng lặp mà không một số công việc:

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

Bạn sẽ thấy cửa sổ không hiển thị hoặc thanh tiến trình vẫn bị đóng băng cho đến khi kết thúc bài tập. Giải thích rất đơn giản: gtk là sự kiện điều khiển và bạn đang đánh cắp kiểm soát khỏi vòng lặp chính gtk, do đó ngăn không cho nó xử lý các sự kiện cập nhật GUI bình thường.

Giải pháp đơn giản nhất bao gồm trên tạm thời cho kiểm soát trở lại GTK mỗi lần tiến độ được thay đổi:

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

Chú ý rằng với giải pháp này, người dùng không thể thoát khỏi ứng dụng (gtk.main_quit sẽ không hoạt động vì vòng lặp mới [gtk.main_iteration()]) cho đến khi công việc nặng của bạn được thực hiện.

Một giải pháp khác bao gồm sử dụng các chức năng nhàn rỗi gtk, được gọi bởi vòng lặp chính gtk bất cứ khi nào nó không có gì để làm. Do đó, gtk nằm trong tầm kiểm soát và chức năng nhàn rỗi phải làm một chút công việc. Nó sẽ trả về True nếu có nhiều việc phải làm, nếu không thì False.

Giải pháp tốt nhất (không có nhược điểm) được James Henstridge chỉ ra. Nó đang tận dụng lợi thế của máy phát điện của python như các chức năng nhàn rỗi, để làm cho python tự động bảo toàn trạng thái cho chúng ta. Nó đi như thế này:

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) 

Các 'trong khi' ở trên chỉ là một ví dụ. Các quy tắc duy nhất là nó sẽ mang lại True sau khi làm một chút công việc và có nhiều việc phải làm, và nó phải mang lại False khi công việc được thực hiện.

1

Nhiều khả năng vấn đề là trong tiến trình gọi lại, là nơi tôi đoán bạn đang cập nhật thanh tiến trình, bạn không thực hiện cuộc gọi để cập nhật màn hình theo cách thủ công tức là chạy qua vòng lặp sự kiện của GUI. Đây chỉ là suy đoán mặc dù, nếu bạn có thể cung cấp thêm mã, nó có thể được dễ dàng hơn để thu hẹp nó xuống hơn nữa.

Lý do bạn cần cập nhật màn hình theo cách thủ công là do chuỗi chính của bạn cũng đang thực hiện tải lên, đó là nơi nó đang chặn.

0

Trong toán hạng số nguyên python 2.x dẫn đến phân chia số nguyên. Hãy thử điều này:

#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) 
0

Vâng, có thể bạn cần đồng thời, và có chủ đề là một cách tiếp cận, nhưng nếu bạn sử dụng đề, hãy sử dụng một phương pháp như thế này một: http://unpythonic.blogspot.com/2007/08/using-threads-in-pygtk.html mà sẽ tóm tắt đi nỗi đau, và cho phép bạn tập trung vào các khía cạnh quan trọng.

(Tôi đã không lặp lại mọi thứ trong bài đăng trên blog đó thông qua sự lười biếng, do đó cộng đồng wiki).

0

Một tùy chọn, nếu bạn không kết hôn với pycurl, là sử dụng trình theo dõi IO của GObject.

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

Sử dụng này bạn có thể interleave các tập tin tải lên với PyGTK vòng lặp sự kiện bình thường, và thậm chí thực hiện cuộc gọi set_progress trong IO bạn xem callback. Nếu bạn đang tải xuống tất cả công việc để tải lên pycurl thì điều này không thực sự khả thi, nhưng nếu bạn chỉ tải lên một tệp qua HTTP, io_add_watch sẽ sử dụng một ổ cắm để giảm đau hơn rất nhiều.

Các vấn đề liên quan