2010-01-01 2 views
0

GUI와 네트워크 프로그래밍과 관련하여이 시점에서 저는 여전히 멍청한 상태입니다. 그래서 이것이 매우 간단한 수정이되기를 바랍니다. 나는 tkinter와 asyncore 모듈에 대해 아주 기본적인 이해를하고있다. 그러나 각각의 프로그램에 소수의 프로그램을 내장하고 있지만, 프로그램에서이 둘을 함께 사용하는 데 어려움을 겪고있다. 모든 중요한 비동기 네트워킹 기능을 얻을 수 없다는 것을 알아 내기 위해서만 전체 UI를 조합했습니다. 간단히하기 위해 나는 기본적인 문제를 설명하기 위해 프로그램을 가장 단순한 형태로 분해했다. Heres는 코드 : I 버튼을 프로그램을 실행하고 클릭하면Asyncore가 Tkinter GUI와 제대로 작동하지 않습니다.

from Tkinter import * 
import asyncore, socket 

class Application(object): 
    def __init__(self, root): 
     mainFrame = Frame(root) 
     mainFrame.grid(column=1, row=1, columnspan=3, rowspan=1) 
     mainButton = Button(mainFrame, text='Click', command=self.makeSocket) 
     mainButton.grid(column=2, row=1, columnspan=1, rowspan=1, pady=7, padx=40) 

    def makeSocket(self): 
     clientSocket() 

class clientSocket(asyncore.dispatcher): 
    def __init__(self): 
     asyncore.dispatcher.__init__(self) 
     self.create_socket(socket.AF_INET, socket.SOCK_STREAM) 
     self.connect(("XXX.XXX.XXX.XXX", XXXX)) 
     print 'init works' 

    def handle_connect(self): 
     print 'connect works' 

root = Tk() 
myApp = Application(root) 
root.after_idle(asyncore.loop) 
root.mainloop() 

그래서, 나는 clientSocket 객체가 초기화되는 것을 나타내는 문자열 '초기화 작동'를 얻을 연결이 성공적으로 이루어집니다. 그러나 handle_connect 메소드는 실행되지 않습니다. 그리고 handle_read 메소드를 구현하고 서버에 명령을 실행하면 (클라이언트에 데이터를 다시 보내기 위해)이 메소드는 호출되지 않습니다. asyncore 루프가 자체적으로 실행되는 것을 막는 일반적인 문제가 있다고 생각합니다. tkinters 이벤트 루프가 범인이 될 수 있다는 것을 알았지 만 GUI가 유휴 상태 일 때 after_idle 메서드가 non-Tkinter 이벤트를 처리 할 수 ​​있다는 인상하에있었습니다. 여전히 문제를 일으키는 tkinter 이벤트 루프입니까 아니면 다른 것일 수 있습니까?

+0

asyncore는 가치가있는 것으로, 표준 라이브러리에서 여전히 호환성을 유지하면서도 매우 어렵고 까다로운 Python 기술로, 현대 프로젝트에서는별로 좋지 않습니다. 더 나은 비동기 프레임 워크가 필요한 경우 Twisted Python을 사용해보십시오. (그리고 나는 Twisted를 가볍게하지 않는 것이 좋습니다!) –

답변

2

여기 몇 가지 문제가 있으며 어떤 것이 있는지 잘 모르겠습니다.

asyncore.loop은 정상적으로 작동 할 때 절대 반환하지 않는 함수입니다. root.mainloop은 아마도 창을 닫을 때까지 결코 반환하지 않는 함수 일 것입니다. 어떤 점에서는 일정 기간 동안 하나의 고리가 다른 고리에 의해 굶어 죽을 것이기 때문에 일이 잘못 될 수 있습니다.

(덧붙여서, 이것이 메인 루프를 교체하고 이벤트 중심 시스템으로 교체하여 사용을 쉽게하려는 프레임 워크를 싫어하는 이유입니다. 두 개 이상의 시스템을 함께 사용해야 할 때까지 훌륭하게 작동합니다. 어느 시점에서 일이 복잡해질 수 있습니다.)

그러나 asyncore.loop이 반복 할 횟수를 제한 할 수 있습니다. 대신 다음을 시도해보십시오.

def poll_asyncore_once(): 
    asyncore.loop(count=1) 

root.after_idle(poll_asyncore_once) 

루프 호출에도 시간 초과 값을 추가 할 수 있습니다.

그러나 여전히 GUI가 asyncore 루프를 입력 한 결과로 이벤트가 없어지더라도 연결이 끝났을 것이라고 생각했습니다. 이것은 다른 무엇인가 잘못되었다는 것을 의미하며, asyncore가 connect() 메소드에서 예외를 발생시키고 TK가 그것을 삼키고있을 가능성이 있습니다. clientSocket에 예외 핸들러를 두어보십시오. 초기화하고 진행 방법을 확인하십시오.

+0

예외 핸들러를 추가했는데 성공적으로 연결이 된 것처럼 보입니다. 나는 알렉스가 아래에 링크 된 조리법을 더 자세히 살펴볼 것이다. 그러나 호기심에서, 내가 원하는 프로그램을 어떻게 만들 수 있을까? 올바르게 이해한다면, asyncore는 모두 select() 및 poll() 함수를 기반으로합니다.그래서 이것들을 사용하는 방법과 GUI에 맞게 만들어진 루프를 만드는 방법을 배우기 만하면됩니까? 그리고 GUI 자체를 만들기 위해 무엇을 사용해야합니까? TK와 Tcl로 만들겠습니까? 아니면 더 좋은 방법이 있습니까? – HoboMo

+0

count 인수를 asyncore.loop에 사용하면 효과적으로 이벤트 구동 시스템이 아닌 콜백이있는 폴링 시스템이되어 문제가 해결되지 않습니다. 나는 Tkinter에 대해서는 언급 할 수 없다. GUI 기반 시스템은 그들이 기반으로하는 전형적인 메시지 대기열 시스템과 일치하기 때문에 이벤트 기반이되는 경향이있다. 유휴 시간을 사용하는 것이 편리하다면 아마 괜찮을 것입니다. – Kylotan

+0

귀하의 실제 문제에 관해서는, 나는 다른 스레드에 무엇이든 넣는 것을 확신하지는 않습니다. (다른 이유로는 더 좋은 해결책 일 수도 있습니다. 추가 로깅을 추가하기 위해 asyncore의 복사본을 수정하고 싶습니다. (비록 이미 사용할 수있는 로깅 훅이 있음을 기억하고 있지만) handle_connect가 호출되지 않는 이유를 알아 냈습니다. – Kylotan

0

asyncore와 Tkinter를 함께 사용하는 방법을 보여주는 Jacob Hallén이 (기본적으로 스레딩 트릭을 사용하여) this recipe을 참조하십시오. (또한 Python Cookbook의 첫 번째 인쇄본에서 조리법 9.6으로, 두 번째 버전에서는 11.4로 확장되었습니다.)

+0

AFAICS 파이썬 요리 책 2 판 11.9 절 –

+0

그 조리법은 asyncore를 전혀 사용하지 않습니다. –

관련 문제