2011-05-01 4 views
1

мир! В черепаховой графике на питоне можно создавать различные объекты Черепахи и манипулировать ими своими методами, вперед, назад ... Я хотел поэкспериментировать с потоками, поэтому я написал потоковый класс MyTurtleManipulator.Tkinter Turtles and Threads

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 

Что это означает, что делает «главная нить не входит в основной цикл ". Спасибо за помощь.

ответ

1

это, кажется, питон/Tkinter ограничение as described here, черепаха и потоки не являются друзьями

+0

О, это грустно ... Спасибо за вашу помощь – rfrm

0

Это имеет свои ограничения, но все-таки возможно. Ответ находится в вашей messges ошибки:

RuntimeError: main thread is not in main loop

Предельных ваши черепахи/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

enter image description here