I have the following code:
import time
def wait10seconds():
for i in range(10):
time.sleep(1)
return 'Counted to 10!'
print(wait10seconds())
print('test')
Now my question is how do you make print('test') run before the function wait10seconds() is executed without exchanging the 2 lines.
I want the output to be the following:
test
Counted to 10!
Anyone know how to fix this?
You can use Threads for this
like:
from threading import Thread
my_thread = Thread(target=wait10seconds) # Create a new thread that exec the function
my_thread.start() # start it
print('test') # print the test
my_thread.join() # wait for the function to end
You can use a Timer. Taken from the Python docs page:
def hello():
print("hello, world")
t = Timer(30.0, hello)
t.start() # after 30 seconds, "hello, world" will be printed
if you are using python 3.5+ you can use asyncio:
import asyncio
async def wait10seconds():
for i in range(10):
await asyncio.sleep(1)
return 'Counted to 10!'
print(asyncio.run(wait10seconds()))
asyncio.run is new to python 3.7, for python 3.5 and 3.6 you won't be able to use asyncio.run but you can achieve the same thing by working with the event_loop directly
Related
Is there any simple way to activate the thread to fire up the function every X sec, to display some data?
def send_data():
data = "Message from client"
socket.sendall(data.encode())
write_thread = threading.Thread(target=send_data())
write_thread.start()
You could try the ischedule module - it provides very straightforward syntax for scheduling any given function.
Here's an example straight from the GitHub page:
from ischedule import run_loop, schedule
#schedule(interval=0.1)
def task():
print("Performing a task")
run_loop(return_after=1)
The return_after param in run_loop() is an optional timeout.
Also, in case you're unfamiliar, the # syntax is a Python decorator.
A simple way would be this:
import time
while True:
task()
time.sleep(1)
I am trying to use asyncio together with threading for a Discord Bot. I've found this script which I changed to my needs:
import time
import threading as th
import asyncio
import discord
class discordvars(object):
client=discord.Client()
TOKEN=('---')
running_discordthread=False
discordloop = asyncio.get_event_loop()
discordloop.create_task(client.start(TOKEN))
discordthread=th.Thread(target=discordloop.run_forever)
def start():
if discordvars.running_discordthread==False:
discordvars.discordthread.start()
print("Discord-Client started...")
discordvars.running_discordthread=True
else:
print("Discord-CLient allready running...")
time.sleep(2)
def stop():
if discordvars.running_discordthread==True:
discordvars.discordloop.call_soon_threadsafe(discordvars.discordloop.stop())
print("Requestet Discord-Client stop!")
discordvars.discordthread.join()
print(discordvars.discordthread.isAlive())
time.sleep(1)
print("Discord-Client stopped...")
discordvars.running_discordthread=False
else:
print("Discord-Client not running...")
time.sleep(2)
#discordvars.client.event
async def on_message(message):
if message.content.startswith('!test'):
embed = discord.Embed(title="test", color=0x0071ce, description="test")
await message.channel.send(embed=embed)
Starting the Script with the start() function works great. Also stopping with the stop() function works somehow. If I call the stop() function it prints: "False" so I am thinking that the thread was stopped. But if I then call the start() function I will get an error:
RuntimeError: threads can only be started once
This script is part of a big project so I am calling the functions from another script. But I think that shouldn't be the problem.
What is the problem? Thanks in advance.
You cannot re-start the existing thread, but you can start a new thread that runs the event loop. You can achieve that by moving the assignment to discordthread to the start function.
And your call to call_soon_threadsafe is wrong. You need to pass discordloop.stop to it, without parentheses. That refers to the actual function without calling it right away, and allows the loop thread to call it, which was intended:
discordloop.call_soon_threadsafe(discordloop.stop)
Finally, your init function is missing a global declaration for the variables you assign that are intended as globals.
I have some difficulties into making this function running in the background without blocking my entire program, how can I run that function in loop, without blocking my entire program?
This is the function:
while True:
schedule.run_pending()
Thank you for any reply.
Edit:
def FunctioninLoop():
while True:
schedule.run_pending()
async def MyFunction():
ScheduleToexecute=schedule.every().minute.do(Functionscheduled)
t = Thread(target=FunctioninLoop())
t.start()
print("The execution is going on")
Threads are what you are looking for.
Consider the following code:
from threading import Thread
def myfunc(a, b, c):
pass
# Creates a thread
t = Thread(target=myfunc, args=(1, 2, 3))
# Launches the thread (while not blocking the main execution)
t.start()
somecode
somecode
somecode
# Waits for the thread to return (not a must)
t.join()
Hope I've helped! :)
import threading
pender = threading.thread(schedule.run_pending) # Does not Block
print("life goes on until...")
pender.join() # Blocks until schedule.run_pending() is complete.
You can use python's subprocess module
https://docs.python.org/3.2/library/subprocess.html
import os
def myfunction():
..........
os.spawnl(os.P_NOWAIT, myfunction())
I would like to call an async function from a pure sync code.
I would like to execute that async function in the background without stucking my prog.
My idea is to use the threading module.
from threading import Thread
import asyncio
async def func1():
...
def func2():
...
if __name__ == '__main__':
Thread(target=func1).start()
Thread(target=func2).start()
Any idea?
Thanks in advance!
Since Python 3.7 there is asyncio.run.
Replace
Thread(target=func1).start()
by
Thread(target=asyncio.run, args=(func1(),)).start()
The documentation for asyncio gives two examples for how to print "Hello World" every two seconds:
https://docs.python.org/3/library/asyncio-eventloop.html#asyncio-hello-world-callback
https://docs.python.org/3/library/asyncio-task.html#asyncio-hello-world-coroutine
I can run those from the interpreter, but if I do I lose access to the interpreter. Can an asyncio event loop be run in the background, so that I can keep typing commands at the interpreter?
Edit:
If using Python 3.8 or above, you should use the asyncio repl, as explained in zeronone's answer. If using 3.7 or lower, you can use this answer.
You can run the event loop inside a background thread:
>>> import asyncio
>>>
>>> #asyncio.coroutine
... def greet_every_two_seconds():
... while True:
... print('Hello World')
... yield from asyncio.sleep(2)
...
>>> def loop_in_thread(loop):
... asyncio.set_event_loop(loop)
... loop.run_until_complete(greet_every_two_seconds())
...
>>>
>>> loop = asyncio.get_event_loop()
>>> import threading
>>> t = threading.Thread(target=loop_in_thread, args=(loop,))
>>> t.start()
Hello World
>>>
>>> Hello World
Note that you must call asyncio.set_event_loop on the loop, otherwise you'll get an error saying that the current thread doesn't have an event loop.
If you want to interact with the event loop from the main thread, you'll need to stick to loop.call_soon_threadsafe calls.
While this kind of thing is an ok way to experiment in the interpreter, in actual programs, you'll probably want all your code running inside the event loop, rather than introducing threads.
With Python 3.8, you can use the new asyncio REPL.
$ python -m asyncio
>>> async def greet_every_two_seconds():
... while True:
... print('Hello World')
... await asyncio.sleep(2)
...
>>> # run in main thread (Ctrl+C to cancel)
>>> await greet_every_two_seconds()
...
>>> # run in background
>>> asyncio.create_task(greet_every_two_seconds())