How to truly implement timeout in python? http://eventlet.net/doc/modules/timeout.html
Code looks like:
#!/usr/bin/python
import eventlet
import time
import sys
import random
while True:
try:
with eventlet.timeout.Timeout(1, False):
print 'limited by timeout execution'
while True:
print '\r' + str(random.random()),
sys.stdout.flush()
eventlet.sleep(0)
print ' Never printed Secret! '
except Exception as e:
print ' Exception: ', e
finally:
print ''
print ' Timeout reached '
print ''
Time out will never reached. Where am I wrong?
P.s. I replaced:
time.sleep(0.1)
with:
eventlet.sleep(0)
Add False for exception, now it works well:
with eventlet.timeout.Timeout(1):
change to:
with eventlet.timeout.Timeout(1, False):
But it works only with eventlet.sleep(0.1)
E.g this code wrong:
#!/usr/bin/python
import eventlet
import time
start_time = time.time()
data = 0
with eventlet.timeout.Timeout(1, False):
while True:
data +=1
print 'Catch data ', data, ' in ', time.time() - start_time
I simply add sleep 0 seconds:
eventlet.sleep(0)
And it works like a charm.
Solved
eventlet's Timeout isn't as magical as you'd hoped. It can only detect timeouts in "greenthreaded" code -- code that uses eventlet's system of cooperative multihtreading. As noted in the Timeout docs, "you cannot time out CPU-only operations with this class". time.sleep pauses with Python's internal threading system, not eventlet's greenthreads.
Instead, use eventlet.sleep which works correctly with greenthreads.
Related
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()
I have a small piece of code that I made to test out and hopefully debug the problem without having to modify the code in my main applet in Python. This has let me to build this code:
#!/usr/bin/env python
import sys, threading, time
def loop1():
count = 0
while True:
sys.stdout.write('\r thread 1: ' + str(count))
sys.stdout.flush()
count = count + 1
time.sleep(.3)
pass
pass
def loop2():
count = 0
print ""
while True:
sys.stdout.write('\r thread 2: ' + str(count))
sys.stdout.flush()
count = count + 2
time.sleep(.3)
pass
if __name__ == '__main__':
try:
th = threading.Thread(target=loop1)
th.start()
th1 = threading.Thread(target=loop2)
th1.start()
pass
except KeyboardInterrupt:
print ""
pass
pass
My goal with this code is to be able to have both of these threads displaying output in stdout format (with flushing) at the same time and have then side by side or something. problem is that I assume since it is flushing each one, it flushes the other string by default. I don't quite know how to get this to work if it is even possible.
If you just run one of the threads, it works fine. However I want to be able to run both threads with their own string running at the same time in the terminal output. Here is a picture displaying what I'm getting:
terminal screenshot
let me know if you need more info. thanks in advance.
Instead of allowing each thread to output to stdout, a better solution is to have one thread control stdout exclusively. Then provide a threadsafe channel for the other threads to dispatch data to be output.
One good method to achieve this is to share a Queue between all threads. Ensure that only the output thread is accessing data after it has been added to the queue.
The output thread can store the last message from each other thread and use that data to format stdout nicely. This can include clearing output to display something like this, and update it as each thread generates new data.
Threads
#1: 0
#2: 0
Example
Some decisions were made to simplify this example:
There are gotchas to be wary of when giving arguments to threads.
Daemon threads terminate themselves when the main thread exits. They are used to avoid adding complexity to this answer. Using them on long-running or large applications can pose problems. Other
questions discuss how to exit a multithreaded application without leaking memory or locking system resources. You will need to think about how your program needs to signal an exit. Consider using asyncio to save yourself these considerations.
No newlines are used because \r carriage returns cannot clear the whole console. They only allow the current line to be rewritten.
import queue, threading
import time, sys
q = queue.Queue()
keepRunning = True
def loop_output():
thread_outputs = dict()
while keepRunning:
try:
thread_id, data = q.get_nowait()
thread_outputs[thread_id] = data
except queue.Empty:
# because the queue is used to update, there's no need to wait or block.
pass
pretty_output = ""
for thread_id, data in thread_outputs.items():
pretty_output += '({}:{}) '.format(thread_id, str(data))
sys.stdout.write('\r' + pretty_output)
sys.stdout.flush()
time.sleep(1)
def loop_count(thread_id, increment):
count = 0
while keepRunning:
msg = (thread_id, count)
try:
q.put_nowait(msg)
except queue.Full:
pass
count = count + increment
time.sleep(.3)
pass
pass
if __name__ == '__main__':
try:
th_out = threading.Thread(target=loop_output)
th_out.start()
# make sure to use args, not pass arguments directly
th0 = threading.Thread(target=loop_count, args=("Thread0", 1))
th0.daemon = True
th0.start()
th1 = threading.Thread(target=loop_count, args=("Thread1", 3))
th1.daemon = True
th1.start()
# Keep the main thread alive to wait for KeyboardInterrupt
while True:
time.sleep(.1)
except KeyboardInterrupt:
print("Ended by keyboard stroke")
keepRunning = False
for th in [th0, th1]:
th.join()
Example Output:
(Thread0:110) (Thread1:330)
Thank you guys for seeing my post.
First, the following is my code:
import os
print("You can create your own message for alarm.")
user_message = input(">> ")
print("\n<< Sample alarm sound >>")
for time in range(0, 3):
os.system('say ' + user_message) # this code makes sound.
print("\nOkay, The alarm has been set.")
"""
##### My problem is here #####
##### THIS IS NOT STOPPED #####
while True:
try:
os.system('say ' + user_message)
except KeyboardInterrupt:
print("Alarm stopped")
exit(0)
"""
My problem is that Ctrl + C does not work!
I tried changing position of try block, and making signal(SIGINT) catching function.
But those also does not work.
I have seen https://stackoverflow.com/a/8335212/5247212, https://stackoverflow.com/a/32923070/5247212, and other several answers about this problem.
I am using MAC OS(10.12.3) and python 3.5.2.
This is expected behaviour, as os.system() is a thin wrapper around the C function system(). As noted in the man page, the parent process ignores SIGINT during the execution of the command. In order to exit the loop, you have to manually check the exit code of the child process (this is also mentioned in the man page):
import os
import signal
while True:
code = os.system('sleep 1000')
if code == signal.SIGINT:
print('Awakened')
break
However, the preferred (and more pythonic) way to achieve the same result is to use the subprocess module:
import subprocess
while True:
try:
subprocess.run(('sleep', '1000'))
except KeyboardInterrupt:
print('Awakened')
break
Your code would then look like something like this:
import subprocess
print("You can create your own message for alarm.")
user_message = input(">> ")
print("\n<< Sample alarm sound >>")
for time in range(0, 3):
subprocess.run(['say', user_message]) # this code makes sound.
print("\nOkay, The alarm has been set.")
while True:
try:
subprocess.run(['say', user_message])
except KeyBoardInterrupt:
print("Alarm terminated")
exit(0)
As an added note, subprocess.run() is only available in Python 3.5+. You can use subprocess.call() to achieve the same effect in older versions of Python.
Also catch "SystemExit"
except (KeyboardInterrupt, SystemExit):
print("Alarm stopped")
The problem seems to be that Ctrl+C is captured by the subprocess you call via os.system. This subprocess reacts correspondingly, probably by terminating whatever it is doing. If so, the return value of os.system() will be not zero. You can use that to break the while loop.
Here's an example that works with me (substituting say by sleep):
import os
import sys
while True:
try:
if os.system('sleep 1 '):
raise KeyboardInterrupt
except KeyboardInterrupt:
print("Alarm stopped")
sys.exit(0)
If Ctrl-C is captured by the subprocess, which is the case here, the simplest solution is to check the return value of os.system(). For example in my case it returns value of 2 if Ctrl-C stops it, which is a SIGINT code.
import os
while True:
r = os.system(my_job)
if r == 2:
print('Stopped')
break
elif r != 0:
print('Some other error', r)
This is my first try with threads in Python,
I wrote the following program as a very simple example. It just gets a list and prints it using some threads. However, Whenever there is an error, the program just hangs in Ubuntu, and I can't seem to do anything to get the control prompt back, so have to restart another SSH session to get back in.
Also have no idea what the issue with my program is.
Is there some kind of error handling I can put in to ensure it doesn't hang.
Also, any idea why ctrl/c doesn't work (I don't have a break key)
from Queue import Queue
from threading import Thread
import HAInstances
import logging
log = logging.getLogger()
logging.basicConfig()
class GetHAInstances:
def oraHAInstanceData(self):
log.info('Getting HA instance routing data')
# HAData = SolrGetHAInstances.TalkToOracle.main()
HAData = HAInstances.main()
log.info('Query fetched ' + str(len(HAData)) + ' HA Instances to query')
# for row in HAData:
# print row
return(HAData)
def do_stuff(q):
while True:
print q.get()
print threading.current_thread().name
q.task_done()
oraHAInstances = GetHAInstances()
mainHAData = oraHAInstances.oraHAInstanceData()
q = Queue(maxsize=0)
num_threads = 10
for i in range(num_threads):
worker = Thread(target=do_stuff, args=(q,))
worker.setDaemon(True)
worker.start()
for row in mainHAData:
#print str(row[0]) + ':' + str(row[1]) + ':' + str(row[2]) + ':' + str(row[3])i
q.put((row[0],row[1],row[2],row[3]))
q.join()
In your thread method, it is recommended to use the "try ... except ... finally". This structure guarantees to return the control to the main thread even when errors occur.
def do_stuff(q):
while True:
try:
#do your works
except:
#log the error
finally:
q.task_done()
Also, in case you want to kill your program, go find out the pid of your main thread and use kill #pid to kill it. In Ubuntu or Mint, use ps -Ao pid,cmd, in the output, you can find out the pid (first column) by searching for the command (second column) you yourself typed to run your Python script.
Your q is hanging because your worker as errored. So your q.task_done() never got called.
import threading
to use
print threading.current_thread().name
I'm attempting to write a Python script that will ping/icmp an IP address and tell me if it's alive. I'm doing this because I have a intermittent issue. I wanted to ping, log the outcome, sleep for a period and attempt the ping again. I tried a while loop, but still getting errors like these:
line 33, in (module) systemPing('192.168.1.1')
line 30, in systemPing time.sleep(30)
KeyboardInterrupt
I'm using Python 2.6.
Ideally my question is how I loop through this method/function systemPing and what errors there are in my code? The script seems to work, but I get these errors when I hit ctrl-c.
from subprocess import Popen, PIPE
import datetime, time, re
logFile = open("textlog.txt", "a")
def getmyTime():
now = datetime.datetime.now()
return now.strftime("%Y-%m-%d %H:%M \n")
startTime = "Starting ..." + getmyTime()
logFile.write(startTime)
logFile.write("\n")
def systemPing(x):
cmd = Popen("ping -n 1 " + x , stdout=PIPE)
#print getmyTime()
for line in cmd.stdout:
if 'timed out' in line:
loggedTime = "Failure detected - " + getmyTime()
logFile.write(loggedTime)
if 'Reply' in line:
print "Replied..."
logFile.close()
print "Sleeping 30mins ... CTRL C to end"
time.sleep(30) #1800 is 30mins
systemPing('192.168.1.1')
if __name__ =='__main__':
systemPing('192.168.1.1')
Any help is always appreciated.
Thank you.
It's not really an error per se, it's just the default behavior for Python, upon receipt of a SIGINT (which is what happens when you press CTRL-C), to raise a KeyboardInterrupt exception.
You'll get the same thing if you send the signal with kill(1), like...
$ kill -INT <pid>
If you want to handle it, then you can change the code to something like...
if __name__ =='__main__':
try:
systemPing('192.168.1.1')
except KeyboardInterrupt:
print 'Finished'
...or whatever you want it to do.