4

有没有办法同时使用两只乌龟在一个窗口中同时画两个圆圈?我尝试了这段代码,但两只海龟在分开的窗口中绘制

from multiprocessing import Process
import turtle

t1=turtle.Turtle()
t2=turtle.Turtle()

def tes1():
  t1.speed(0)
  i=0
  while i < 360:
    t1.forward(1)
    t1.left(1)
    i+=1

def tes2():
  t2.speed(0)
  i=0
  while i < 360:
    t2.forward(1)
    t2.right(1)
    i+=1

if __name__ == '__main__':
  p1 = Process(target=tes1)
  p1.start()
  p2 = Process(target=tes2)
  p2.start()
  p1.join()
  p2.join()

但有人告诉我尝试多线程,但这段代码有一个严重的语义错误!

import threading
import turtle

t1=turtle.Turtle()
t2=turtle.Turtle()

def tes1():
  t1.speed(0)
  i=0
  while i < 360:
    t1.forward(1)
    t1.left(1)
    i+=1

def tes2():
  t2.speed(0)
  i=0
  while i < 360:
    t2.forward(1)
    t2.right(1)
    i+=1

t = threading.Thread(target=tes1)
t.daemon = True  # thread dies when main thread (only non-daemon thread) exits.
t.start()

t3 = threading.Thread(target=tes2)
t3.daemon = True  # thread dies when main thread (only non-daemon thread) exits.
t3.start()

多处理或多线程的最佳建议是什么?

4

6 回答 6

8

...我想要多线程或多处理的答案,我坚持要这样做。

如果我们小心地走钢丝,只有主线程发出海龟命令,turtle 模块可以与线程一起使用:

import queue
import threading
import turtle

def tes1():
    for _ in range(360):
        graphics.put(turtle1.forward)
        graphics.put(turtle1.left)

def tes2():
    for _ in range(360):
        graphics.put(turtle2.forward)
        graphics.put(turtle2.right)

def process_queue():
    while not graphics.empty():
        (graphics.get())(1)

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

graphics = queue.Queue(1)  # size = number of hardware threads you have - 1

turtle1 = turtle.Turtle('turtle')
turtle1.speed('fastest')
thread1 = threading.Thread(target=tes1)
thread1.daemon = True  # thread dies when main thread (only non-daemon thread) exits.
thread1.start()

turtle2 = turtle.Turtle('turtle')
turtle2.speed('fastest')
thread2 = threading.Thread(target=tes2)
thread2.daemon = True  # thread dies when main thread (only non-daemon thread) exits.
thread2.start()

process_queue()

turtle.exitonclick()

我们使用 queue 模块进行线程安全通信。

在此处输入图像描述

于 2017-06-29T19:31:34.427 回答
2

海龟真的有必要在不同的线程中吗?那这个呢?

import turtle

t1 = turtle.Turtle()
t2 = turtle.Turtle()

t1.speed(0)
t2.speed(0)
for i in range(360):
  t1.forward(1)
  t1.left(1)
  t2.forward(1)
  t2.right(1)
于 2013-10-21T15:28:12.100 回答
1

一次8只乌龟也没问题

import turtle
turtle.delay(0)

t = [turtle.Turtle() for i in range(8)]

for i, j in enumerate(t):
    j.right(i*45)
    j.speed(0)

for i in range(360):
    for j in t:
        j.forward(1)
        j.right(1)
于 2013-10-21T15:36:21.523 回答
1

我创建了一个threaded_turtle包,它利用 的功能queue.Queue在主线程中无缝执行所有海龟指令,而代码仍然像海龟在不同线程中运行一样编写。

threaded_turtle在 GitLab 上:https ://gitlab.com/zvone/threaded_turtle

使用该软件包,问题中的代码只需稍作修改即可工作:

import turtle
from threaded_turtle import ThreadSerializer, TurtleThread

ctrl = ThreadSerializer()                        ## <-- create a serializer

t1=turtle.Turtle()
t2=turtle.Turtle()

def tes1(t1):                                    ## <-- additional argument
  t1.speed(0)
  i=0
  while i < 360:
    t1.forward(1)
    t1.left(1)
    i+=1

def tes2(t2):                                    ## <-- additional argument
  t2.speed(0)
  i=0
  while i < 360:
    t2.forward(1)
    t2.right(1)
    i+=1

t = TurtleThread(ctrl, t1, target=tes1)          ## <-- additional arguments
t.daemon = True
t.start()

t3 = TurtleThread(ctrl, t2, target=tes2)         ## <-- additional arguments
t3.daemon = True
t3.start()

ctrl.run_forever(1)                              ## <-- run the serializer

结果:

两只乌龟同时盘旋的截图

于 2018-06-04T21:25:20.270 回答
1

我认为 Beazley 宣扬的协程和生成器(第 447 页)在这里更合乎逻辑:

注意:deque来自collections模块的也更可靠。

import turtle
from collections import deque


def move1():
    for _ in range(360):
        turtle1.forward(1)
        turtle1.left(1)
        yield


def move2():
    for _ in range(360):
        turtle2.forward(1)
        turtle2.right(1)
        yield


# Create turtles
turtle1 = turtle.Turtle('turtle')
turtle1.speed('fastest')
turtle2 = turtle.Turtle('turtle')
turtle2.speed('fastest')

# Create and populate a task queue

taskqueue = deque()
taskqueue.append(move1())  # Add tasks (generators)
taskqueue.append(move2())

while taskqueue:   # Run all of the tasks
    # Get the next task
    task = taskqueue.pop()
    try:
        # Run it to the next yield and enqueue
        next(task)
        taskqueue.appendleft(task)
    except StopIteration:
        # Task is done
        pass

turtle.done()
于 2018-07-07T22:36:07.437 回答
0

turtle 模块不支持多线程。我认为你在这里唯一能做的就是其他人已经建议过的:做一堆乌龟。或者,您可以使用 mtTkinter 之类的东西,它与 tkinter 完全相同,但支持线程。

于 2013-12-27T19:46:39.360 回答