Executing multiple Python commands at once - python

I was wondering what the easiest way to execute two or more commands at the same time in python. For example:
from turtle import *
turtle_one=Turtle()
turtle_two=Turtle()
turtle_two.left(180)
#The lines to be executed at the same time are below.
turtle_one.forward(100)
turtle_two.forward(100)

You can effectively do this using the timer event that comes with the turtle module:
from turtle import Turtle, Screen
turtle_one = Turtle(shape="turtle")
turtle_one.setheading(30)
turtle_two = Turtle(shape="turtle")
turtle_two.setheading(210)
# The lines to be executed at the same time are below.
def move1():
turtle_one.forward(5)
if turtle_one.xcor() < 100:
screen.ontimer(move1, 50)
def move2():
turtle_two.forward(10)
if turtle_two.xcor() > -100:
screen.ontimer(move2, 100)
screen = Screen()
move1()
move2()
screen.exitonclick()
With respect to threads, as suggested by others, read up on the issues discussed in posts like Multi threading in Tkinter GUI as Python's turtle module is built on Tkinter and that recent post notes:
a lot of GUI toolkits are not thread-safe, and tkinter is not an
exception

Try using the threading module.
from turtle import *
from threading import Thread
turtle_one=Turtle()
turtle_two=Turtle()
turtle_two.left(180)
Thread(target=turtle_one.forward, args=[100]).start()
Thread(target=turtle_two.forward, args=[100]).start()
This starts the turtle_one/two.forward function in the background, with 100 as an argument.
To make it easier, make a run_in_background function...
def run_in_background(func, *args):
Thread(target=func, args=args).start()
run_in_background(turtle_one.forward, 100)
run_in_background(turtle_two.forward, 100)

Related

Pygame mixer causes tkinter to freeze

to-speech module to say a list and the audio module I am using is mixer form pygame. When i start playing the audio the tkinter program can not be interacted with and if I move the window the audio stops. I think some sort of threading may fix this but I am not sure how that works.
Problem
Tkinter window freezes.
Goal
To be able to interact with the program when audio is playing.
Code
import tkinter as tk
from gtts import gTTS
from io import BytesIO
import pygame
window = tk.Tk()
window.geometry("800x600")
window.resizable(0, 0)
def speak(text,language="en",accent="com"):
mp3_fp = BytesIO()
phrase = gTTS(text=text,lang=language,tld=accent)
phrase.write_to_fp(mp3_fp)
pygame.init()
pygame.mixer.init()
pygame.mixer.music.load(mp3_fp,"mp3")
pygame.mixer.music.play()
while pygame.mixer.music.get_busy():
pygame.time.delay(10)
pygame.event.poll()
def play():
data = list([boy,girl,pink,blue])
for i in data:
speak(i)
window.mainloop()
Code Explanation
The play()passes each value in the dictionary E.g. Boy, Girl to speak() separately where they are played one by one consecutively
In the speak() the audio from the text-to-speech module (gTTS) gets passed to pygame.mixer where it is played when the last word has been said.
First of all you need to post the minimum code necessary to demonstrate your problem. You haven't done that. Fortunately, this is a well-known "problem" and easy to answer without importing four libraries and building an application around what you've provided in order to answer it.
Secondly -- in the code that you have provided, data = list[boy,girl,pink,blue] isn't even proper syntax. It should be data = list(["boy", "girl", "pink", "blue"]). You have to post running code to get the best answers.
Lecture over.
The issue is that conventional unmodified Python runs in a single thread. If you want to know why that is then I invite you to research the GIL (Global Interpreter Lock) for more background.
There's only one thread, and when PyGame is doing something then the thread is busy and TkInter stops responding to input, and vice versa -- when TkInter is in the middle of something you'll find that PyGame stops responding.
You can demonstrate this phenomenon with this:
import tkinter as tk
import time
def delay():
time.sleep(10)
def main():
root = tk.Tk()
tk.Button(root, text="Test Me", command=delay).pack(expand=True, fill=tk.BOTH)
root.mainloop()
if __name__ == "__main__":
main()
When you run this you'll see that the button is depressed, the button stays depressed while the application goes to sleep, and the button doesn't go back to its unclicked status until after it wakes up.
The only way I know of to get around your particular problem is by running TkInter and/or PyGame on separate threads.
You are going to have to read up on Python's Threading() module. You might start here. I've browsed it and it seems to be pretty complete.
Just to demonstrate the difference:
import tkinter as tk
import time
import threading
def delay():
print("Delay started...")
time.sleep(10)
print("... and finished.")
def dispatchDelayToThread():
t = threading.Thread(target=delay)
t.start()
def main():
root = tk.Tk()
tk.Button(root, text="Test Me", command=dispatchDelayToThread).pack(expand=True, fill=tk.BOTH)
root.mainloop()
if __name__ == "__main__":
main()
I didn't even really change the code any! I added a function to dispatch the code I'd already written then changed the button to call the dispatcher instead of the code. Very easy to implement.
Run this and you'll see that the button returns to ready right away. If you run this from the command line you'll see that it prints a line when you enter the thread, and another line when the thread completes. And an even cooler thing is that if you click the button three times in a row you'll get three "starting" message, followed by three "finished" messages shortly afterwards.
To demonstrate this threading using your own code:
import pygame
import tkinter as tk
import io
import gtts
import threading
def speak(text,language="en",accent="com"):
mp3_fp = io.BytesIO()
phrase = gtts.gTTS(text=text,lang=language,tld=accent)
phrase.write_to_fp(mp3_fp)
pygame.init()
pygame.mixer.init()
pygame.mixer.music.load(mp3_fp,"mp3")
pygame.mixer.music.play()
while pygame.mixer.music.get_busy():
pygame.time.delay(10)
pygame.event.poll()
def dispatchPlay():
t = threading.Thread(target=play)
t.start()
def play():
data = list(["boy", "girl", "pink", "blue"])
for i in data:
speak(i)
def main():
root = tk.Tk()
root.geometry('300x200')
tk.Button(root, text="This is a clicky button", command=dispatchPlay).pack(expand=True, fill=tk.BOTH)
root.mainloop()
if __name__ == "__main__":
main()
Generally you would have your user interface on one thread, frame updates on another thread if it's a game, sound stuff on yet another thread, networking connection on a thread, etc., with all of them tied together through some kind of messaging system.
Note well, however, that in conventional unmodified Python there is only ever one thread running at any one time! You can have a hundred threads spawned, but only one of them will run at a time. Python sucks at multithreading computationally-intensive tasks, but shines in threading out I/O stuff that you usually just spend your time waiting on.

My turtle module code is executing the first part but not the second part. Both parts are working fine on their own

I'm making a simple snake game in python. I am in the earlier stages of just making the snake move at this point. So I have 3 files, main.py, Turtle_Skin.py and Turtle_Control.py
The first part (In Turtle_Skin.py) is working just fine where I need to make the snake take the starting position, however even if I try migrating the code from Turtle_Control.py to main.py (to make sure it executes and doesn't get left behind while importing), it won't execute
My Code with file names:
main.py:
from Turtle_Control import *
from Turtle_Skin import *
positions_goto()
Turtle_Skin.py:
from turtle import *
screen = Screen()
screen.setup(width=600, height=600)
screen.bgcolor("black")
screen.title("Snake_Food_Game")
screen.tracer(1)
Baby_Turtle = Turtle()
Mommy_Turtle = Turtle()
Daddy_Turtle = Turtle()
All_Turtles = [Baby_Turtle, Mommy_Turtle, Daddy_Turtle]
for turtle in All_Turtles:
turtle.shape("square")
turtle.pencolor("white")
turtle.color("white")
def positions_goto():
Daddy_Turtle.penup()
Daddy_Turtle.goto(x=-40, y=0)
Mommy_Turtle.penup()
Mommy_Turtle.goto(x=-20, y=0)
Baby_Turtle.penup()
positions_goto()
screen.exitonclick()
Turtle_Control.py
from Turtle_Skin import *
import time
positions_goto()
is_on = True
while is_on:
screen.update()
time.sleep(0.1)
for part_num in range(len(All_Turtles) - 1, 0, -1):
xcord = All_Turtles[part_num - 1].xcor()
ycord = All_Turtles[part_num - 1].ycor()
All_Turtles[part_num].goto(x=xcord, y=ycord)
Baby_Turtle.forward(20)
screen.exitonclick() blocks your code, running the main turtle loop, until you click the screen.
Tracing the code execution:
main.py runs from Turtle_Control import * on line 1
Turtle_Control.py runs from Turtle_Skin import * on line 1
Turtle_Skin.py runs most of the turtle code, then blocks at screen.exitonclick(). After you click, only then does from Turtle_Skin import * on line 1 of Turtle_Control.py resolve so that line 2, import time, can continue. But by then the window's been destroyed so the while loop is much too late.
A good way to figure out what's going on with this behavior is to add print()s to your code to see if the code you care about is even executing, and if so, when. Creating a minimal example of the problem would make the issue obvious:
import turtle
turtle.exitonclick() # => blocks until the screen is clicked
print("hi") # => only executes after the screen was clicked
The original code organization doesn't make much sense. Modules have no obvious responsibility. positions_goto() is called in many different locations. The main code that initializes turtles and runs the game loop is spread across a few files seemingly haphazardly.
With such a small amount of code, creating modules seems premature here. I'd put all of the code into one file until you have things working ("I am in the earlier stages of just making the snake move at this point") and really need obvious separation of concerns. When you do, I'd create different files for different classes (things/entities in the game), primarily. snake.py with class Snake: would be one example. food.py with class Food: might be another potential file.
There should be no "loose" code in the global scope in each file other than a class or function or two. Main-line code (particularly if non-idempotent) in modules should be in an if __name__ == "__main__": block so that it's not invoked simply because the module was imported (which might happen multiple times in an app, as is the case here).
If you want to separate the whole game from main, that's fine, but keep the set up and main loop intact so they execute as a unit.

how to thread multiple turtle heads in python?

I made a recursive star for Art with Technology. My teacher wants me to make similar stars in 4 corners, I accomplished that too, but the screen recording is too big, hence I need them to run simultaneously, (currently they run after a star is completed). I tried threading but It does'nt do anything
Here is a minimal code:
from turtle import *
import threading
from itertools import permutations
from random import choice
import concurrent.futures
screen=Screen()
def star_multiple(turtle):
# repeatedly calls draw star function
def pen(foo):
# a convenient tool to do all penup/pendown
def drawstar(turtle,l,colors):
# draws a star of edge=l param.
a,b,c,d=Turtle(),Turtle(),Turtle(),Turtle()
pen('penup')
a.goto(-500,200)# the turtle go to their position(works)
b.goto(500,200)
c.goto(-500,-200)
d.goto(500,-200)
pen('pendown')
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
executor.map(star_multiple,[a,b,c,d])# This doesn't work,
done()
drawstar function
output I am getting

Python: Making Background Image with Turtles

I am trying to insert a .gif file as a background image in my turtle world for a separate turtle to travel on, but I can't get it to work. I'm new to python and any help would be great.
Here's the current code:
from turtle import *
from Tkinter import *
def test():
turtle.bgpic("warehouse1.gif")
fd(100)
goto(50, 100)
from turtle import * makes available all names in the turtle module so you could use bare bgpic() in this case:
#!/usr/bin/env python
from turtle import *
def test():
speed(1) # set the slowest speed to see the turtle movements
bgpic('warehouse1.gif')
fd(100)
goto(50, 100)
mainloop()
test()
Note: In general you should not use wildcard imports (*) outside a Python interactive shell. See Idioms and Anti-Idioms in Python.

Multiple GUI screens from same python program

I've made a pathfinding visualizer using python and pygame. As of now, it can simulate only one algorithm at a time. I want to spawn multiple windows, each simulating different algorithm, side by side so that algorithms can be analyzed against each other. I have a function client.run() that draws the GUI. I'm trying to spawn multiple instances like this:
p=threading.Thread(target = client.run)
q=threading.Thread(target = client.run)
p.start()
q.start()
But by doing so my program hangs! Is there any way to rectify this problem, or any alternative way of running multiple instances/windows?
Pygame is built in a way to have a single window by process, you can't avoid that. The pygame.display module sets you a "display" and that is what you get.
You are in good look, as you have designed you software to work with threads, and have each thread control a display.. Just change the "threading" Python module for the multiprocessing, and use multiprocessing.Process instead of threading.Threads -- as long as you initialize pygame and its display from within each subprocess you should be ok.
I just teste here and teh example bellow works fine:
# -*- coding: utf-8 -*-
import pygame
import multiprocessing
from time import sleep
def init():
pygame.init()
screen = pygame.display.set_mode((320,240))
return screen
def main():
screen = init()
while True:
pygame.event.pump()
event = pygame.event.poll()
if event.type != pygame.NOEVENT:
print event
class Multigame(multiprocessing.Process):
def run(self):
return main()
for i in range(3):
Multigame().start()
while True:
sleep(1)

Categories

Resources