2017-03-16 3 views
1

나는 서버 스크립트 실행이 있습니다 만 현재 시간을 3 초마다 전송, 제대로 작동tkinter의 스레드에서 실행중인 websocket 아래로 메시지를 보낼 수 있습니까?

async def give_time(websocket,path): 
    while True: 
     await websocket.send(str(datetime.datetime.now())) 
     await asyncio.sleep(3) 

start_server = websockets.serve(give_time, '192.168.1.32', 8765) 

asyncio.get_event_loop().run_until_complete(start_server) 
asyncio.get_event_loop().run_forever() 

.

는이 코드를 실행하는 클라이언트에서 해당 문자열을받을 수 있습니다 : 내가 메인 스레드에서 tkinter.mainloop을 실행할 수 있도록

async def hello(): #takes whatever text comes through the websocket and displays it in the socket_text label. 

    async with websockets.connect('ws://wilsons.lan:8765') as ws: 
     while True: 
      text = await ws.recv() 
      logger.info('message received through websocket:{}'.format(text)) 
      socket_text.configure(text=text) #socket_text is a tkinter object 

loop = asyncio.new_event_loop() 

def socketstuff(): 
    asyncio.set_event_loop(loop) 
    asyncio.get_event_loop().run_until_complete(hello()) 

t = threading.Thread(target=socketstuff,daemon=True) 

그것은 스레드에서 실행됩니다. 이것은 내가 threading을 사용했을 때 처음으로 번 이었기 때문에 나는 잘못 이해하고있는 것 같지만 현재는 효과가있는 것 같습니다.

내가해야 할 일은 tkinter 이벤트 (현재 텍스트 상자 옆에있는 버튼을 클릭하기 만하면되지만 좀 더 복잡한 작업)를 기반으로 websocket 아래로 메시지를 보낼 수 있도록하는 것입니다. 클릭 부분이 제대로 작동합니다.

메시지를 보내는 데 많은 문제가 있습니다. 나는 asyncawait의 유무에 관계없이 많은 다른 것들을 시도했지만, 그것은 당황한 것일 수도 있습니다.

외부에서 ws에 액세스 할 수없는 주된 문제는 그 기능이 hello() 인 것 같습니다. 이는 콘텍스트 관리자 with을 사용함에있어 의미가 있습니다. 그러나, 단지 ws = websockets.connect('ws://host')을 사용하는 경우 send (또는 실제로 recv) 메소드를 사용하려고 시도하는 websockets.py35.client.Connect object을 얻게되면 object has no attribute 'send' 오류가 발생합니다.

충분한 정보가 있기를 바랍니다. 필요한 것이 있으면 언제든지 게시 해주세요.

+0

문제를 좀더 생각해 보면, 내가 잘못 작성한 것처럼 보입니다. 스레딩은 문제가 아닙니다.'tkinter.mainloop()'가 asyncio 메인 루프에서 실행되도록 변경했습니다. 이제는 스레딩이 필요 없습니다. 그러나 컨텍스트 관리자 외부에서 websocket에 액세스 할 때의 문제점은 여전히 ​​남아 있습니다. 지금 시도 할 것은 tkinter 이벤트에 asyncio.queue를 사용하여 websocket 메시지 작업을 추가하고 asyncio 함수를 사용하여 대기열에서 가져와 asyncio 기능을 수행하는 것입니다. 그것이 효과가 있다면 답변을 게시 할 것입니다! –

답변

0

이 문제를 해결하는 가장 좋은 방법은 스레드를 사용하는 이 아니라입니다.

This post 내가 해결하는 데 도움이되었습니다.

async def do_gui(root,interval=0.05): 
    while True: 
     root.update() 
     await asyncio.sleep(interval) 

그러나, 웹 소켓 메시지를 생성하는 Tkinter의 이벤트를 얻을 수있는 가장 좋은 방법은 asyncio.queue을 사용하는 것입니다 : 그것은 당신이, 코 루틴에서의 Tkinter 주회 돌이의 하나 반복을 실행할 수 있음을 보여줍니다. tkinter 콜백을 작성하면 put_nowait()을 사용하여 큐에 항목을 추가하고 do_gui과 동시에 실행되는 coroutine을 사용하면 await queue.get()을 사용하여 대기열에서 메시지를 가져옵니다.