Python 2.7 使用Tkinter(有时)headless或root.after()的替换运行Python
我有下面的工作代码 我有一套用Python操作的机器。我在Tkinter中有一个gui,但这些机器通常是无头运行的,python代码在启动时自动启动 我非常喜欢使用root.after()启动多个任务并让它们继续运行的设计模式。我的问题是,这来自Tkinter库,当运行headless时,行“root=Tk()”将抛出一个错误 我有两个问题Python 2.7 使用Tkinter(有时)headless或root.after()的替换运行Python,python-2.7,tkinter,headless,Python 2.7,Tkinter,Headless,我有下面的工作代码 我有一套用Python操作的机器。我在Tkinter中有一个gui,但这些机器通常是无头运行的,python代码在启动时自动启动 我非常喜欢使用root.after()启动多个任务并让它们继续运行的设计模式。我的问题是,这来自Tkinter库,当运行headless时,行“root=Tk()”将抛出一个错误 我有两个问题 我可以执行一些技巧让代码忽略没有显示的事实吗 或 是否有与Tkinter“root.after(time_in_ms,function_to_call)”的
和穿线
after()和mainloop()创建自己的taks管理器
简单例子
import time
class TaskManager():
def __init__(self):
self.tasks = dict()
self.index = 0
self.running = True
def after(self, delay, callback):
# calcuate time using delay
current_time = time.time()*1000
run_time = current_time + delay
# add to tasks
self.index += 1
self.tasks[self.index] = (run_time, callback)
# return index
return self.index
def after_cancel(self, index):
if index in self.tasks:
del self.tasks[index]
def mainloop(self):
self.running = True
while self.running:
current_time = time.time()*1000
# check all tasks
# Python 3 needs `list(self.tasks.keys())`
# because `del` changes `self.tasks.keys()`
for key in self.tasks.keys():
if key in self.tasks:
run_time, callback = self.tasks[key]
if current_time >= run_time:
# execute task
callback()
# remove from list
del self.tasks[key]
# to not use all CPU
time.sleep(0.1)
def quit(self):
self.running = False
def destroy(self):
self.running = False
# --- function ---
def stop_saying_hello():
global count
global h
global c
if count > 10:
root.after_cancel(h)
print "counting cancelled"
else:
c = root.after(200, stop_saying_hello)
def hello():
global count
global h
print "hello", count
count += 1
h = root.after(1000, hello)
# --- main ---
count = 0
h = None
c = None
root = TaskManager()
h = root.after(1000, hello) # time in ms, function
c = root.after(200, stop_saying_hello)
d = root.after(12000, root.destroy)
root.mainloop()
什么错误?始终对完整的错误消息提出疑问。请参阅-fake display请参阅线程处理,您可以始终在()之后创建自己的
。它将函数添加到特殊列表中,并且mainloop
一直循环并检查此列表中的元素。在3.4+中,还可以使用asyncio及其等价物执行定时任务。回答非常好。我用xvfb做了一个测试,程序执行起来很好!。我认为定制任务管理器是更好的可维护性解决方案。我可以在代码中使用注释更容易地解释目的。谢谢
import time
class TaskManager():
def __init__(self):
self.tasks = dict()
self.index = 0
self.running = True
def after(self, delay, callback):
# calcuate time using delay
current_time = time.time()*1000
run_time = current_time + delay
# add to tasks
self.index += 1
self.tasks[self.index] = (run_time, callback)
# return index
return self.index
def after_cancel(self, index):
if index in self.tasks:
del self.tasks[index]
def mainloop(self):
self.running = True
while self.running:
current_time = time.time()*1000
# check all tasks
# Python 3 needs `list(self.tasks.keys())`
# because `del` changes `self.tasks.keys()`
for key in self.tasks.keys():
if key in self.tasks:
run_time, callback = self.tasks[key]
if current_time >= run_time:
# execute task
callback()
# remove from list
del self.tasks[key]
# to not use all CPU
time.sleep(0.1)
def quit(self):
self.running = False
def destroy(self):
self.running = False
# --- function ---
def stop_saying_hello():
global count
global h
global c
if count > 10:
root.after_cancel(h)
print "counting cancelled"
else:
c = root.after(200, stop_saying_hello)
def hello():
global count
global h
print "hello", count
count += 1
h = root.after(1000, hello)
# --- main ---
count = 0
h = None
c = None
root = TaskManager()
h = root.after(1000, hello) # time in ms, function
c = root.after(200, stop_saying_hello)
d = root.after(12000, root.destroy)
root.mainloop()