【问题标题】:Multithreading With Python Turtle使用 Python Turtle 进行多线程
【发布时间】:2013-10-21 15:19:46
【问题描述】:

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

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()

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

【问题讨论】:

    标签: python multithreading python-3.x turtle-graphics


    【解决方案1】:

    ...我想要多线程或多处理的答案,我坚持 就可以了。

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

    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()
    

    我们正在使用队列模块进行线程安全通信。

    【讨论】:

      【解决方案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)
      

      【讨论】:

      • 您的回答对两只海龟有好处,但假设我们有 8 只海龟,我们想命令它们同时绘制,所以我们的处理速度非常低!
      • 也许mtTkinter可以帮助你。如果你想制造超级高效的海龟,我认为你走的不是正确的道路
      • 我认为这是一个糟糕的解决方案,因为与 cdlane 给出的解决方案相反,您无法单独管理每只海龟的绘制。
      【解决方案3】:

      一次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)
      

      【讨论】:

      • 这是真的,但我想要多线程或多处理的答案,我坚持要这样做。
      【解决方案4】:

      我创建了一个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
      

      结果:

      【讨论】:

      • 你如何安装你的模块,当我去你的存储库时我没有看到 setup.py
      • @yemi.JUMP 只需将 threaded_turtle 包(即目录)放在 pythonpath 中的某个位置,例如在您的源代码旁边。
      【解决方案5】:

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

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

      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()
      

      【讨论】:

        【解决方案6】:

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

        【讨论】:

          猜你喜欢
          • 2016-08-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多