1

世界!在 python 中的海龟图形中,可以创建各种 Turtle 对象并使用它们的方法来操作它们,向前、向后……我想用线程进行实验,所以我编写了一个名为 MyTurtleManipulator 的线程类。

from threading import Thread
from cTurtle import Turtle 
import random

class MyTurtleManipulator(Thread):
  def __init__(self, turtle):
    Thread.__init__(self)
    self.turtle=turtle
  def run(self):
    actions=[Turtle.forward, Turtle.right, Turtle.left]    
    while True:      
      action=random.choice(actions)      
      action(self.turtle, random.randint(1,25))

turtles=[Turtle() for i in range(5)]
threads=[MyTurtleManipulator(turtle) for turtle in turtles]

for thread in threads:
  print(thread)
  thread.start()

通过实验,我希望看到所有海龟“同时”随机移动,但是当我运行程序时,我得到了这些错误:

<MyTurtleManipulator(Thread-1, initial)>
<MyTurtleManipulator(Thread-2, initial)>
<MyTurtleManipulator(Thread-3, initial)>
<MyTurtleManipulator(Thread-4, initial)>
<MyTurtleManipulator(Thread-5, initial)>
>>> Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python3.1/threading.py", line 516, in _bootstrap_inner
    self.run()
  File "/home/rfrm/test.py", line 13, in run
    action(self.turtle, random.randint(1,25))
  File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 1162, in forward
    checkargs((int, float))
  File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 1131, in _go
    ende = self._position + self._orient * distance
  File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 2266, in _goto
    (start, self._position),
  File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 419, in _drawline
    cl.append(-y)
  File "<string>", line 1, in coords
  File "/usr/lib/python3.1/tkinter/__init__.py", line 2123, in coords
    self.tk.call((self._w, 'coords') + args)))
RuntimeError: main thread is not in main loop

Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib/python3.1/threading.py", line 516, in _bootstrap_inner
    self.run()
  File "/home/rfrm/test.py", line 13, in run
    action(self.turtle, random.randint(1,25))
  File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 1203, in right
    checkargs((int, float))
  File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 2300, in _rotate
    self._orient = self._orient.rotate(delta)
  File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 2085, in _update
    for t in screen._turtles:
  File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 2219, in _drawturtle
    screen._drawpoly(titem, shape, fill=fc, outline=oc,
  File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 384, in _drawpoly
    cl.append(-y)
  File "<string>", line 1, in coords
  File "/usr/lib/python3.1/tkinter/__init__.py", line 2123, in coords
    self.tk.call((self._w, 'coords') + args)))
RuntimeError: main thread is not in main loop

Exception in thread Thread-3:
Traceback (most recent call last):
  File "/usr/lib/python3.1/threading.py", line 516, in _bootstrap_inner
    self.run()
  File "/home/rfrm/test.py", line 13, in run
    action(self.turtle, random.randint(1,25))
  File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 1162, in forward
    checkargs((int, float))
  File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 1131, in _go
    ende = self._position + self._orient * distance
  File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 2270, in _goto
    screen._drawline(self.drawingLineItem, ((0, 0), (0, 0)),
  File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 419, in _drawline
    cl.append(-y)
  File "<string>", line 1, in coords
  File "/usr/lib/python3.1/tkinter/__init__.py", line 2123, in coords
    self.tk.call((self._w, 'coords') + args)))
RuntimeError: main thread is not in main loop

Exception in thread Thread-4:
Traceback (most recent call last):
  File "/usr/lib/python3.1/threading.py", line 516, in _bootstrap_inner
    self.run()
  File "/home/rfrm/test.py", line 13, in run
    action(self.turtle, random.randint(1,25))
  File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 1162, in forward
    checkargs((int, float))
  File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 1131, in _go
    ende = self._position + self._orient * distance
  File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 2270, in _goto
    screen._drawline(self.drawingLineItem, ((0, 0), (0, 0)),
  File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 419, in _drawline
    cl.append(-y)
  File "<string>", line 1, in coords
  File "/usr/lib/python3.1/tkinter/__init__.py", line 2123, in coords
    self.tk.call((self._w, 'coords') + args)))
RuntimeError: main thread is not in main loop

Exception in thread Thread-5:
Traceback (most recent call last):
  File "/usr/lib/python3.1/threading.py", line 516, in _bootstrap_inner
    self.run()
  File "/home/rfrm/test.py", line 13, in run
    action(self.turtle, random.randint(1,25))
  File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 1203, in right
    checkargs((int, float))
  File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 2300, in _rotate
    self._orient = self._orient.rotate(delta)
  File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 2085, in _update
    for t in screen._turtles:
  File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 2219, in _drawturtle
    screen._drawpoly(titem, shape, fill=fc, outline=oc,
  File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 384, in _drawpoly
    cl.append(-y)
  File "<string>", line 1, in coords
  File "/usr/lib/python3.1/tkinter/__init__.py", line 2123, in coords
    self.tk.call((self._w, 'coords') + args)))
RuntimeError: main thread is not in main loop

这是什么意思,“主线程不在主循环中”是什么意思。谢谢您的帮助。

4

2 回答 2

1

这似乎是这里描述的 python/tkinter 限制,乌龟和线程不是朋友

于 2011-05-01T06:37:54.453 回答
0

这有其局限性,但仍有可能。答案在您的错误消息中:

RuntimeError:主线程不在主循环中

将您的turtle/tkinter 操作限制在主线程中。在我对您下面的示例的修改中,我使用线程安全队列数据结构在线程和海龟之间进行通信:

from threading import Thread, active_count
from turtle import Turtle, Screen
import queue
import random

QUEUE_SIZE = 1  # set higher the more hardware threads you have
ACTIONS = [Turtle.forward, Turtle.right, Turtle.left]
COLORS = ['red', 'black', 'blue', 'green', 'magenta']

class MyTurtleManipulator(Thread):

    def __init__(self, turtle):
        super().__init__()
        self.turtle = turtle

    def run(self):
        for _ in range(100):
            actions.put((self.turtle, random.choice(ACTIONS), random.randint(1, 30)))

def process_queue():
    while not actions.empty():
        turtle, action, argument = actions.get()
        action(turtle, argument)

    if active_count() > 1:
        screen.ontimer(process_queue, 100)

actions = queue.Queue(QUEUE_SIZE)

for color in COLORS:
    turtle = Turtle('turtle')
    turtle.color(color)
    turtle.setheading(random.randint(0, 360))
    MyTurtleManipulator(turtle).start()

screen = Screen()

process_queue()

screen.mainloop()

我将 QUEUE_SIZE 设置为 1,因为我在只有两个线程的机器上!我很想知道在具有更多线程和 QUEUE_SIZE ~= #threads - 1 的机器上是否一切正常

在此处输入图像描述

于 2017-06-29T05:21:45.490 回答