Run function every 5 minutes while running main program - python

I want a function to run every 5 minutes while the main program is still running.
I've found multiple posts on how to make a function run every few seconds but they don't seem to work for me.
This is my program:
from Read import getUser, getMessage
from Socket import openSocket, sendMessage
from Initialize import joinRoom, Console
from question import query_yes_no
from Settings import AIDENT
import string
import sched, time
import urllib.parse
import requests
import subprocess
import sys
import os
s = openSocket()
joinRoom(s)
while True:
try:
try:
readbuffer = s.recv(1024)
readbuffer = readbuffer.decode()
temp = readbuffer.split("\n")
readbuffer = readbuffer.encode()
readbuffer = temp.pop()
except:
temp = ""
for line in temp:
if line == "":
break
if "PING" in line and Console(line):
msgg = (("PONG tmi.twitch.tv\r\n").encode())
print(msgg)
s.send(msgg)
break
user = getUser(line)
message = getMessage(line)
print (user + " > " + message)
PMSG = "/w " + user + " "
if "!ping" in message:
sendMessage(s, "PONG ( i'm working fine )")
except:
pass
I need to run sendMessage() function every 5 minutes without interrupting main program.

You have use threading in case , where your main method will keep on exeuting in separate thread and repeater function will execute after every nth sec
sample code would be like this :
import threading
def printit():
threading.Timer(5.0, printit).start()
print "Hello, World!"
printit()
Give it a try by your self .

You should be using threads. This will create a thread, which simply executes your code and sleeps for 5 min. Instead of running your function, run the last two commands to create the thread and start it.
import threading
import time
def pong():
while True:
sendMessage(s, "PONG ( i'm working fine )")
time.sleep(300)
t = threading.Thread(target=pong, args=(,))
t.start()

Related

writing to text file within thread python

I am trying to run this script in the background of a flask web app. This is an example code of what I am trying to do without the PIR sensor connected. I am essentially running this infinite loop and would like to write to a file periodically within a thread. I do not understand what is wrong and why the file is empty.
import threading
from datetime import datetime as dt
from time import sleep
global_lock = threading.Lock()
def write_to_file():
while global_lock.locked():
continue
def motionlog():
global_lock.acquire()
f = open("motionlog.txt", mode = "w")
f.write("Motion Detection Log" + "\n")
while True:
#output_lock.acquire()
f.write("Motion Detected at "+ dt.now().strftime("%m_%d_%Y-%I:%M:%S_%p")+"\n")
print('Motion Detected')
sleep(5)
global_lock.release()
t1 = threading.Thread(target=motionlog)
t1.start()
t1.join()

I try to do a threading system in Python but I can't

I'm trying to make a threading system that continuously runs a while cycle but at the same time performs another function that is waiting for a string.
For example, a while cycle to write "Hello World" and a function waiting for something to be typed.
So i try with this code but it's not worked :(
import threading
from time import sleep
import time
data = []
def get_input():
data.append(input()) # Something akin to this
return data
input_thread = threading.Thread(target=get_input)
input_thread.start()
while (True):
print ("Hello World")
time.sleep(1)
input_thread.join()
if data.pop=="a":
print ("This message will be writed, only when user typed something")
A few things.
Check the array length before popping
The input thread must have a loop also
You need to press enter when you input a string
Here is the updated code:
import threading
from time import sleep
import time
data = []
def get_input():
while True:
data.append(input()) # must press enter to submit
input_thread = threading.Thread(target=get_input)
input_thread.start()
while (True):
print ("Hello World")
time.sleep(1)
if (len(data) and data.pop()=="a"):
print ("This message will be writed, only when user typed something")
input_thread.join() # never gets here

Why does this Python code take 2 minutes to exit when it cannot connect to OBS software?

I am new to Python and i don't know much about asyncio. I want to run this script and if the OBS software it is trying to connect to on 10.11.0.124 is not running to exit the code. The code does this, but it take 2 minutes before it exits. I cannot figure out why it does not exit immediately when it cannot connect to the OBS software that is not running on 10.11.0.124.
#! /usr/bin/python3
import asyncio
import urllib.request
import sys
import datetime
from obswsrc import OBSWS
from obswsrc.requests import StartStopStreamingRequest
def logger(logmessage):
f = open("log.txt", "a")
f.write(str(datetime.datetime.now()) + " " + logmessage + "\n")
f.close
async def main():
try:
async with OBSWS('10.11.0.124', 4444, "password") as obsws:
logger("Connection established.")
while True:
event = await obsws.event()
logger(str(format(event.type_name)))
if(format(event.type_name) == "StreamStarting"):
HitURLToLoadAsset = urllib.request.urlopen("http://10.11.0.159/api/v1/assets/control/asset&b0983c0918b94856900040d9a9e8bdbf").read()
logger(str(HitURLToLoadAsset))
if(format(event.type_name) == "StreamStopped"):
HitURLToLoadAsset = urllib.request.urlopen("http://10.11.0.159/api/v1/assets/control/asset&3b2fb67002364b269d0c2674a628533c").read()
logger(str(HitURLToLoadAsset))
logger("Connection terminated.")
except OSError:
logger("OBS IS NOT RUNNING")
except:
logger(str(sys.exc_info()[1]))
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()
The OBSWS function has a timeout of two minutes, because it uses the websockets module internally and that has a default timeout of two minutes.
Detailed breakdown:
async with OBSWS(...): calls OBSWS.__init__ and then awaits OBSWS.__aenter__.
OBSWS.__init__ does nothing interesting, but OBSWS.__aenter__ awaits OBSWS.connect
OBSWS.connect awaits websocket.connect.
websockets.connect has several different timeouts defined via keyword arguments. It also waits for multiple things. These are:
self._creating_connection, defined here
This uses loop.create_connection which has a 60 second timeout by default.
It then calls factory which calls create_protocol which defaults to klass which defaults to WebSocketClientProtocol, which subclasses WebSocketCommonProtocol which probably isn't adding any further delays.
protocol.handshake(...)
protocol.fail_connection() in the case of any exception being raised, which does occur.
I don't understand asyncio so I just stopped here; there's probably another 60 second delay somewhere but if not... perhaps the computer was just slow.
Thanks for the help user4815162342 and wizzwizz4! Here is my final solution.
I ended up going with wizzwizz4's suggestion of breaking down the connection string so i could use asyncio.wait_for on it.
If anyone cares the code itself is to watch OBS and when streaming is started go change the asset on Screenly OSE to display the RTMP stream. When the streaming is stopped switch back to a different asset on Screenly OSE.
#! /usr/bin/python3
import asyncio
import urllib.request
import sys
import datetime
from obswsrc import OBSWS
from obswsrc.requests import StartStopStreamingRequest
def logger(logmessage):
f = open("log.txt", "a")
f.write(str(datetime.datetime.now()) + " " + logmessage + "\n")
f.close
async def main():
try:
obsws = OBSWS('10.11.0.124', 4444, "password")
# if no response from OBS in 30 seconds EXIT
await asyncio.wait_for(obsws.connect(), timeout=30)
logger("Connection established.")
while True:
event = await obsws.event()
logger(str(format(event.type_name)))
if(format(event.type_name) == "StreamStarting"):
HitURLToLoadAsset = urllib.request.urlopen("http://10.11.0.159/api/v1/assets/control/asset&b0983c0918b94856900040d9a9e8bdbf").read()
logger(str(HitURLToLoadAsset))
if(format(event.type_name) == "StreamStopped"):
HitURLToLoadAsset = urllib.request.urlopen("http://10.11.0.159/api/v1/assets/control/asset&3b2fb67002364b269d0c2674a628533c").read()
logger(str(HitURLToLoadAsset))
except asyncio.TimeoutError:
logger("OBS NOT RUNNING-- TIMEOUT!")
except OSError:
logger("OBS IS NOT RUNNING")
except:
logger(str(sys.exc_info()[1]))
finally:
await obsws.close()
logger("Connection terminated.")
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()

Get live value of variable from another script

I have two scripts, new.py and test.py.
Test.py
import time
while True:
x = "hello"
time.sleep(1)
x = "world"
time.sleep(1)
new.py
import time
while True:
import test
x = test.x
print(x)
time.sleep(1)
Now from my understanding this should print "hello" and a second later "world" all the time when executing new.py.
It does not print anything, how can i fix that?
Thanks
I think the code below captures what you are asking. Here I simulate two scripts running independently (by using threads), then show how you can use shelve to communicate between them. Note, there are likely much better ways to get to what you are after -- but if you absolutely must run the scripts independently, this will work for you.
Incidentally, any persistent source would do (such as a database).
import shelve
import time
import threading
def script1():
while True:
with shelve.open('my_store') as holder3:
if holder3['flag'] is not None: break
print('waiting')
time.sleep(1)
print("Done")
def script2():
print("writing")
with shelve.open('my_store') as holder2:
holder2['flag'] = 1
if __name__ == "__main__":
with shelve.open('my_store') as holder1:
holder1['flag'] = None
t = threading.Thread(target=script1)
t.start()
time.sleep(5)
script2()
t.join()
Yields:
waiting
waiting
waiting
waiting
waiting
writing
Done
Test.py
import time
def hello():
callList = ['hello', 'world']
for item in callList:
print item
time.sleep(1)
hello()
new.py
from parent import hello
while True:
hello()

Updating lines in terminal while doing other stuff on the last one in Python?

I am trying to write a Python program that tracks the prices of the stock market and outputs it to the user refreshing the same line through stderr, that's a simplified version of the code (used randint just to check that the program was doing something):
import random
import schedule
import time
import sys
def printran():
a = "\rFirst Line is: " + str(random.randint(1,10))
sys.stderr.write(a)
schedule.every(2).seconds.do(printran)
while True:
schedule.run_pending()
time.sleep(1)
My problems are:
a) How do I "refresh"the console output on multiple lines?
I tried stuff like:
a = "\rFirst Line is: " + str(random.randint(1,10)) + "\n\rSecond Line is: " + str(random.randint(2,20))
but the output is a mess and obviously the \n command will always generate a new line
b) since the while function doesn't really end I cannot do other stuff, do I need to use multithreading?
c) finding a solution that is as much as possible easy, portable and OS agnostic (must work on Linux, OSX, Win).
import random
import schedule
import threading
import time
def printran():
print("First Line is: " + str(random.randint(1,10)))
def run():
schedule.every(2).seconds.do(printran)
while True:
schedule.run_pending()
time.sleep(1)
if __name__ == "__main__":
t = threading.Thread(target=run)
t.start()
Also, you can use APScheduler
But in the following code sched.start() won't wait and it will stop with main.
import random
from apscheduler.schedulers.background import BackgroundScheduler
import time
def printran():
print("First Line is: " + str(random.randint(1,10)))
if __name__ == "__main__":
sched = BackgroundScheduler()
sched.add_job(printran, 'interval', seconds=2)
sched.start()
# wait 10 seconds and exit
time.sleep(10)
Should be crossplatform (I didn't check on Win, Mac, but it works on linux)

Categories