扩展 Tic-tac-toe 游戏的功能 (gtk + decorators + raw_input)
Extending the functionality of the Tic-tac-toe game (gtk + decorators + raw_input)
前段时间我在 Python (2.7) 中写了一个简单的井字棋游戏,带有服务器脚本(每个连接线程)和客户端脚本的多人游戏版本。现在我想用 gtk 扩展客户端。我希望这是使用装饰器的一个例子。客户端脚本的工作方式是通过提示检索数据。我想编写一个脚本,类似于客户端的补丁(只是装饰客户端函数,调用新的 gtk-client 脚本和 wallah)。我想那样做:
- gtk-client 在线程
中从客户端脚本启动 run_game() 函数
- 负责用户输入的函数有装饰器,它执行代码并在最后将数据放入提示(这可能吗?)
这是我通过gtk接口控制客户端脚本的想法,但是我遇到了一些问题:
- 是否可以像键盘输入一样把数据放到提示中?
- 如果不在主线程中,是否可以从 raw_input() 获取数据?
编辑:
好的,我找到了解决方案。我将创建装饰器来覆盖 raw_input() 函数(猴子路径)。它应该是这样的:
- gtk-client 使用 run_game() 函数创建线程。来自客户
- run_game() 修饰(函数调用前覆盖 raw_input())
- 现在 raw_input() 通过队列等待来自 gtk-client 的输入数据 (queue.get())
这看起来是个不错的解决方案,但这是我的另一个问题。我的 gtk-client 调用线程 (run_game())。如果我不使用 thread.join(),我的线程将在执行中被阻塞,或者打印函数无法将整个数据打印到控制台。如果我使用 thread.join() 会产生冲突,因为线程等待队列中的数据。示例测试代码:
gtk-client.py
import gtk
import client as cliApp
from threading import Thread
from Queue import Queue
# gtk stuff etc...
# lets say it is called on y_button_click, part of GameGtk class
def y_button_click(self, widget):
cliApp.q.put('test msg')
# lets say that it is called in x_button_click
@run_game_decorator(func):
def wrapper(*args):
# some connecting/logging stuff
cliApp.q = Queue()
t = Thread(target = cliApp.test)
t.start()
# t.join() - worked until I added q.get() to new raw_input()
return wrapper
# gtk still working after this function
client.py
def new_raw_input(label):
print label
return q.get()
def test():
print 'Thread start'
raw_input = new_raw_input
a = raw_input("Type something: ")
print a
print 'Thread finished'
在这种情况下,我的线程只打印 'Thread start'。如何处理这个问题?
好的,我终于找到了所有问题的解决方案。要模拟用户对 raw_input() 的输入,只需更改函数功能(猴子修补),如问题、编辑部分所示。
关于在控制台中打印错误 - 我通过将 sys.stdout.flush() 添加到刷新缓冲区(解释为 here)并在将数据放入队列后等待线程来解决它。
gtk-client.py
import gtk
import client as cliApp
from threading import Thread
from Queue import Queue
from time import sleep
import sys
# gtk stuff etc...
# lets say it is called on y_button_click, part of GameGtk class
def y_button_click(self, widget):
cliApp.q.put('test msg')
self.t.join()
# lets say that it is called in x_button_click
@run_game_decorator(func):
def wrapper(*args):
# some connecting/logging stuff
cliApp.q = Queue()
gtkWindow.t = Thread(target = cliApp.test)
gtkWindow.t.start()
sleep(0.1)
sys.stdout.flusch()
return wrapper
# gtk still working after this function
前段时间我在 Python (2.7) 中写了一个简单的井字棋游戏,带有服务器脚本(每个连接线程)和客户端脚本的多人游戏版本。现在我想用 gtk 扩展客户端。我希望这是使用装饰器的一个例子。客户端脚本的工作方式是通过提示检索数据。我想编写一个脚本,类似于客户端的补丁(只是装饰客户端函数,调用新的 gtk-client 脚本和 wallah)。我想那样做:
- gtk-client 在线程 中从客户端脚本启动 run_game() 函数
- 负责用户输入的函数有装饰器,它执行代码并在最后将数据放入提示(这可能吗?)
这是我通过gtk接口控制客户端脚本的想法,但是我遇到了一些问题:
- 是否可以像键盘输入一样把数据放到提示中?
- 如果不在主线程中,是否可以从 raw_input() 获取数据?
编辑: 好的,我找到了解决方案。我将创建装饰器来覆盖 raw_input() 函数(猴子路径)。它应该是这样的:
- gtk-client 使用 run_game() 函数创建线程。来自客户
- run_game() 修饰(函数调用前覆盖 raw_input())
- 现在 raw_input() 通过队列等待来自 gtk-client 的输入数据 (queue.get())
这看起来是个不错的解决方案,但这是我的另一个问题。我的 gtk-client 调用线程 (run_game())。如果我不使用 thread.join(),我的线程将在执行中被阻塞,或者打印函数无法将整个数据打印到控制台。如果我使用 thread.join() 会产生冲突,因为线程等待队列中的数据。示例测试代码:
gtk-client.py
import gtk
import client as cliApp
from threading import Thread
from Queue import Queue
# gtk stuff etc...
# lets say it is called on y_button_click, part of GameGtk class
def y_button_click(self, widget):
cliApp.q.put('test msg')
# lets say that it is called in x_button_click
@run_game_decorator(func):
def wrapper(*args):
# some connecting/logging stuff
cliApp.q = Queue()
t = Thread(target = cliApp.test)
t.start()
# t.join() - worked until I added q.get() to new raw_input()
return wrapper
# gtk still working after this function
client.py
def new_raw_input(label):
print label
return q.get()
def test():
print 'Thread start'
raw_input = new_raw_input
a = raw_input("Type something: ")
print a
print 'Thread finished'
在这种情况下,我的线程只打印 'Thread start'。如何处理这个问题?
好的,我终于找到了所有问题的解决方案。要模拟用户对 raw_input() 的输入,只需更改函数功能(猴子修补),如问题、编辑部分所示。
关于在控制台中打印错误 - 我通过将 sys.stdout.flush() 添加到刷新缓冲区(解释为 here)并在将数据放入队列后等待线程来解决它。
gtk-client.py
import gtk
import client as cliApp
from threading import Thread
from Queue import Queue
from time import sleep
import sys
# gtk stuff etc...
# lets say it is called on y_button_click, part of GameGtk class
def y_button_click(self, widget):
cliApp.q.put('test msg')
self.t.join()
# lets say that it is called in x_button_click
@run_game_decorator(func):
def wrapper(*args):
# some connecting/logging stuff
cliApp.q = Queue()
gtkWindow.t = Thread(target = cliApp.test)
gtkWindow.t.start()
sleep(0.1)
sys.stdout.flusch()
return wrapper
# gtk still working after this function