I am detecting whether the external IP has changed with miniupnpc. And during my testing I've noticed that when I turn off Wi-Fi (disconnect my pc from the internet) I get an error which I cannot catch with the exception.
It appears to be printed to the console.
u = miniupnpc.UPnP()
u.discoverdelay = config.svc_upnp_disc_delay
try:
discover = u.discover()
print(discover, 'device(s) detected')
if discover:
u.selectigd()
while True:
stat_info, stat_port, stat_error = u.statusinfo()
if stat_info == 'Connected':
if u.lanaddr != os.environ.get(config.envr_name_int_addr):
os.environ[config.envr_name_int_addr] = u.lanaddr
ext_ip = u.externalipaddress()
if ext_ip != os.environ.get(config.envr_name_ext_addr):
os.environ[config.envr_name_ext_addr] = ext_ip
print('+', end=' ', flush=True)
else:
print('-', end=' ', flush=True)
if stat_info != os.environ.get(config.envr_svc_status):
os.environ[config.envr_svc_status] = stat_info
time.sleep(5)
except Exception as e:
print('Exception :', e)
This is the error:
sendto: Network is unreachable
sendto: Network is unreachable
sendto: Network is unreachable
sendto: Network is unreachable
Is there any way I can catch this so I can log it in a log file instead of the console?
And what is causing it in the first place...because I am not printing it?
The fact that there are 4 errors being logged indicates that your try...except block might not work correctly.
Try using BaseException instead of Exception in your except clause.
Related
What My Code is Supposed to Do: (Ran inside docker) My code uses the Mysterium network (Pretty much just a VPN but it's decentralized) to generate a list of active nodes and then cycles through each one and runs my web scraper. If the node fails the Have_Internet function then that node gets added to the blacklist.
Issue 1: I want to generate new node -> test connection (either just by ping test or short network strength test) -> Run selenium. I only want to run Selenium if the network test passes otherwise blacklist that node and try again. I cannot run the Have_Internet function in an else statement because then it will never run for some reason. I read that the else statement will only run if the try successes which is what I want, but then it never runs so I took it out.
Issue 2: I have kept checking my blacklist file and it never has anything in it so either my code block responsible for printing it fails or my network test is garbage.
Issue 3: I used some bash commands in my python code because I could not figure out a simple solution. if you made them into python lines I would be very happy.
PS. Any other general feedback is more than welcome. I am still pretty new to python :)
Cheers in advance
def Run_Selenium():
# Doing stuff
def Random_Node():
# Doing stuff
def Have_Internet():
conn = httplib.HTTPSConnection("8.8.8.8", timeout=5)
try:
conn.request("HEAD", "/")
return True
except Exception:
return False
finally:
conn.close()
if __name__ == "__main__":
while True == True:
#gets new node
random_node = Random_Node()
Temp_Random_Node = Random_Node()
try:
print("Running new myst session", flush=True)
os.system("/opt/myst/myst connection down") # stops vpn
#time.sleep(5)
#New_Myst_Command = () # makes node command
os.system(str("/opt/myst/myst connection up " + Temp_Random_Node)) # starts new connection with node
#time.sleep(5) # time to wait while dvpn starts
# catch errors when connecting to new node
except Exception as e:
print(e, flush=True)
print("Failed to connect to " + Temp_Random_Node + " moving on anyway and adding it to the blacklist", flush=True)
os.system("echo " + Temp_Random_Node + " >> /root/Dockerdata/blacklist.txt")
Connected = Have_Internet()
if Connected == True:
print("Going to try to run selenium", flush=True)
time.sleep(random.randrange(1, 20)) # 4, 305 # amount of time to wait before loading the page again
try:
Run_Selenium()
print("Just ran a successful run of selenium", flush=True)
except Exception as e:
print("Selenium failed")
print(e, flush=True)
else:
print("Failed network check")
os.system("echo " + random_node + " > /root/Dockerdata/blacklist.txt")
I want to replace Cron Jobs for "keeping" my program alive because it calls every XX interval whether or not the scrip is already called, creating duplicate entries.
I investigated the issue, and had a few approaches. One was to modify my program so it checks if it is already called and closes itself. The one I went after was to detach it completely from Cronjob by calling itself over and over again with execfile which works exactly how I want except the following problem:
RuntimeError: maximum recursion depth exceeded
Is there a way to keep the program in "infinite loop" without getting a Stack Overflow?
Here is my code, its a program that checks Mails, and converts them into MySQL DB entries.
imap = imaplib.IMAP4(hst)
try:
imap.login(usr, pwd)
except Exception as e:
errormsg = e
time.sleep(30)
print "IMAP error: " + str(errormsg)
execfile('/var/www/html/olotool/converter.py')
raise IOError(e)
# Authentification & Fetch Step
while True:
time.sleep(5)
'''
The script will always result in an error if there
are no mails left to check in the inbox. It then
goes into sleep mode and relaunches itself to check
if new mails have arrived.
'''
try:
imap.select("Inbox") # Tell Imap where to go
result, data = imap.uid('search', None, "ALL")
latest = data[0].split()[-1]
result, data = imap.uid('fetch', latest, '(RFC822)')
raw = data[0][1] # This contains the Mail Data
msg = email.message_from_string(raw)
except Exception as e:
disconnect(imap)
time.sleep(60)
execfile('/var/www/html/olotool/converter.py')
raise IOError(e)
I solved the problem myself with the only way I see it possible right now.
First I changed my exception in above code:
except Exception as e:
disconnect(imap)
print "Converter: No messages left"
raise os._exit(0)
# This is a special case since this Exception is
# no error thus os._exit(0) gives no false-positives
As you see I refrain from using execfile now. Instead I wrote a controller script that checks the status of my converter.py and launches it if it is not already running:
while True:
presL = os.popen('pgrep -lf python').read()
print "________________________________________"
print "Starting PIDcheck"
print "Current Processes: "
print presL # Check Processes
presRconverter = find('\d{7} python converter.py', presL)
if presRconverter:
# Store the PID
convPID = find('\d{7}', presRconverter)
print "Converter is running at PID: " + convPID
else:
print "PID Controller: Converter not running"
try:
print "PID Controller: Calling converter"
subprocess.check_call('python converter.py', shell=True)
except subprocess.CalledProcessError as e:
errormsg = e
print "Couldn't call Converter Module"
sendMail(esender,ereceiver,esubject,etext,server)
print "Error notification send"
raise IOError(e)
# If we got until here without ERROR, the call was Successfull
print "PID Controller: Call successful"
print "________________________________________"
time.sleep(60)
This method does not raise an: RuntimeError: maximum recursion depth exceeded. Also this provides you with a nohup.out file if you run the controller with command nohup python converter.py where you can see any problems for errorhandling.
I hope I could help anyone running into the same issue.
Something along the lines of this should work without having to resort to subprocess checking and such:
def check_mail_loop():
imap = imaplib.IMAP4(hst)
# Build some function to login, and, in the event of an error, sleep for n seconds and call login function again.
imap.login(usr, pwd)
while True:
try:
imap.select("Inbox")
result, data = imap.uid('search', None, "ALL")
if result and data:
latest = data[0].split()[-1]
result, data = imap.uid('fetch', latest, '(RFC822)')
raw = data[0][1] # This contains the Mail Data
msg = email.message_from_string(raw)
time.sleep(5)
except SomeRelevantException as e:
logging.log(e)
time.sleep(60)
pass
In the event of some random error that you didn't foresee, use a process control manager like supervisord or monit.
Every now and then setting up a tunnel using sshtunnel.py fails because the gateway (ssh_host) complains the first time I connect to it. I would like to give it a few retries before giving up:
for attempt in range(5):
try:
forwarder.start()
except Exception, e:
print 'Error (trying again in five seconds):\n' + format(e.message))
time.sleep(5)
else:
break
else:
print 'Failed to setup a connection to the gateway'
sys.exit(1)
However, the error is not 'detected'. I took a peek in the sshtunnel.py code and found that the following code catches the related Paramiko exception:
except paramiko.ssh_exception.AuthenticationException:
self.logger.error('Could not open connection to gateway')
return
How do I catch this in my try:?
An SSHTunnel.py project member advised me to add forwarder._check_is_started() to my code:
for attempt in range(5):
try:
forwarder.start()
forwarder._check_is_started()
except BaseSSHTunnelForwarderError as e:
print 'Error (trying again in five seconds):\n' + format(e.message))
time.sleep(5)
else:
break
else:
print 'Failed to setup a connection to the gateway'
sys.exit(1)
Here's the code giving me issues:
def connect(self):
self.chatlog['state'] = NORMAL
self.chatlog.insert(END, ("===ATTEMPTING TO CONNECT TO SERVER\n"))
self.chatlog['state'] = DISABLED
self.chatlog.yview(END)
try:
s.connect((host,port))
self.chatlog['state'] = NORMAL
self.chatlog.insert(END, ("===CONNECTED TO SERVER\n"))
self.chatlog['state'] = DISABLED
self.chatlog.yview(END)
self.conn=True
print("Connected")
except ConnectionRefusedError:
self.chatlog['state'] = NORMAL
self.chatlog.insert(END, ("===SERVER COULD NOT BE FOUND\n" + "===PLEASE MAKE SURE THE SERVER IS ON, AND YOU'RE CONNECTED TO THE NETWORK\n"))
self.chatlog['state'] = DISABLED
self.chatlog.yview(END)
else:
self.chatlog['state'] = NORMAL
self.chatlog.insert(END, ("===THERE'S AN ERROR WITH THE PROGRAM\n" + "===PLEASE TURN IT OFF AND ON AGAIN\n"))
self.chatlog['state'] = DISABLED
self.chatlog.yview(END)
When I connect to a server, it both connects (the "try" section completes fine, the print statement occurs) however the "else" section also occurs. I can't seem to find why. Does anyone have any idea what's causing this?
EDIT: I should say that when I remove the "else:" section, it works fine as well.
I'm guessing you are trying to catch all exceptions here, but that's not the correct syntax.
The correct way to do it would be:
try:
# do something dangerous
except ConnectionRefusedError:
# handle known error
except:
# handle unknown error
else in this case means that the code will be executed if no errors occur.
The else part of a try: except: else: finally: block is similar to the else in an if: else:, effectively:
if someerror:
...
else:
...
The else block runs when no error is raised from the try block. Using this block allows you to minimise the code in the try block; in your case:
try:
s.connect((host,port))
except ConnectionRefusedError:
self.chatlog['state'] = NORMAL
self.chatlog.insert(END, ("===SERVER COULD NOT BE FOUND\n" + "===PLEASE MAKE SURE THE SERVER IS ON, AND YOU'RE CONNECTED TO THE NETWORK\n"))
self.chatlog['state'] = DISABLED
self.chatlog.yview(END)
else:
self.chatlog['state'] = NORMAL
self.chatlog.insert(END, ("===CONNECTED TO SERVER\n"))
self.chatlog['state'] = DISABLED
self.chatlog.yview(END)
self.conn=True
print("Connected")
I want to create socket errors (By doing things, obviously) but I've no idea how I should test if my script handles errors properly (If it dectes them.)
Currently, my code is this:
except socket.error as err:
print "Connection lost, waiting..."
time.sleep(5)
In theory, it should handle all the socket errors, print and then sleep (It's a part of a while loop.).
Any idea of how can I test it to see how it handles errors?
Use the raise statement:
try:
raise socket.error
except socket.error as err:
print "Connection lost, waiting..."
time.sleep(5)
Yet another example:
try:
raise AttributeError
except AttributeError:
print 'Sorry'
#Sorry
Also take a look at here and here