문제

파이썬 프로그램에서 파일을 인터넷에 업로드하고 GTK 진행률 표시 줄을 사용하여 업로드 진행 상황을 표시합니다. 그러나 IM이 직면 한 문제는 업로드가 완료 될 때까지 진행률 표시 줄에 활동이 표시되지 않으며 갑자기 업로드를 완료 함을 나타냅니다. http 요청을하기 위해 pycurl을 사용하고 있습니다 ... 내 질문은 - 파일을 업로드하고 동시에 GUI를 업데이트하려면 멀티 스레드 응용 프로그램이 필요합니까? 아니면 내가 만드는 다른 실수가 있습니까?

미리 감사드립니다!

도움이 되었습니까?

해결책

나는 인용 할 것이다 Pygtk FAQ:

창 안에 진행률 표시 줄을 만들고 작업을 수행하는 루프를 실행하기 시작합니다.

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

이 솔루션을 사용하면 Heavy_Work가 완료 될 때까지 새로운 루프 [gtk.main_iteration ()]로 인해 응용 프로그램을 종료 할 수 없습니다 (GTK.Main_Quit).

또 다른 솔루션은 GTK 유휴 기능 사용으로 구성되며, 할 일이 없을 때마다 GTK 메인 루프에서 호출됩니다. 따라서 GTK는 제어 중이며 유휴 기능은 약간의 작업을 수행해야합니다. 더 많은 작업이 수행되면 참으로 반환됩니다. 그렇지 않으면 거짓입니다.

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'은 그 예일뿐입니다. 유일한 규칙은 약간의 작업을 수행 한 후에는 사실을 양보해야한다는 것입니다.해야 할 일이 더 많으며 작업이 완료되면 허위가 있어야합니다.

다른 팁

문제는 진행 상황에서 진행률 표시 줄을 업데이트하고 있다고 가정 한 상황에서 GUI의 이벤트 루프를 통해 실행되는 디스플레이를 수동으로 업데이트하는 호출을하지 않을 것입니다. 이것은 더 많은 코드를 제공 할 수 있다면 더 이상 좁히는 것이 더 쉬울 수 있습니다.

디스플레이를 수동으로 업데이트 해야하는 이유는 기본 스레드가 업로드를 수행하기 때문에 차단되는 곳입니다.

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)

예, 동시성이 필요할 것입니다. 예 스레드는 하나의 접근 방식이지만 스레드를 사용하는 경우 다음과 같은 메소드를 사용하십시오. http://unpythonic.blogspot.com/2007/08/using-threads-in-pygtk.html 이것은 고통을 추상화하고 중요한 측면에 집중할 수있게 해줄 것입니다.

(나는 그 블로그 게시물의 게으름을 통해 모든 것을 반복하지 않았으므로 커뮤니티 위키).

Pycurl과 결혼하지 않은 경우 한 가지 옵션은 GoBject의 IO 감시자를 사용하는 것입니다.

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

이를 사용하면 파일 업로드를 일반 Pygtk 이벤트 루프와 인터 리브하고 IO 시계 콜백에서 set_progress 호출을 수행 할 수도 있습니다. pycurl에 업로드하기위한 모든 작업을 오프로드하는 경우 실제로는 실현 가능하지 않지만 HTTP에 파일을 업로드하는 경우 IO_ADD_WATCH는 소켓을 훨씬 덜 고통스럽게 사용합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top