Is there a possibility to check on Runtime errors? It is clear from a string that pri1nt is a function and it is not defined in this string.
import ast
def is_valid_python(code):
try:
ast.parse(code)
except SyntaxError:
return False
return True
mycode = 'pri1nt("hello world")'
is_valid_python(mycode) # true
exec(mycode) # NameError: name 'pri1nt' is not defined
Try using BaseException instead of SyntaxError. This would check every type of python error, including NameError. Also, because ast.parse never raises any errors, you should use exec instead.
So it should be like this:
def is_valid_python(code):
try:
exec(code)
except BaseException:
return False
Return True
mycode = 'pri1nt("hello world")'
is_valid_python(mycode) # false
maybe something like this?
import subprocess
script_string = "prnt(\"Hello World!\")"
proc = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
res = proc.communicate(bytes(script_string, "UTF-8"))
what it basically does is pipeing the string to a python interpreter. if no error, then the script_string is valid.
Edit: res will contain (stdout_data, stderr_data) (see https://docs.python.org/3/library/subprocess.html#subprocess.Popen.communicate)
Related
As I'm new in python coding, I stuck on defining a function which take as input variable from other function. Generally my code is :
#!/usr/bin/python
import configparser
import re
var="abc"
class Config:
def getSources(var):
config = configparser.ConfigParser()
config.read("C\\configFile.ini")
connection=config.get(connectinfo,'connectStr')
if source in connection_source:
print (connection_connectstr)
else:
print ('Something wrong')
return connection
try:
emp1 = Config.getSources(var)
except configparser.NoSectionError:
print ("Senction is not correct")
def getTables(connection)
In few words, I get data from Config.ini file, then do some process. Next I want to create next function getTables which as input take result from first function. By the way in getSources I would like to make it as return statement, unfornatelly return is returning null... Print works fine.
You need to return the value or raise an exception:
if source in connection_source:
return (connection_connectstr)
else:
raise configparser.NoSectionError('Something wrong')
I have a python script, tutorial.py. I want to run this script from a file test_tutorial.py, which is within my python test suite. If tutorial.py executes without any exceptions, I want the test to pass; if any exceptions are raised during execution of tutorial.py, I want the test to fail.
Here is how I am writing test_tutorial.py, which does not produce the desired behavior:
from os import system
test_passes = False
try:
system("python tutorial.py")
test_passes = True
except:
pass
assert test_passes
I find that the above control flow is incorrect: if tutorial.py raises an exception, then the assert line never executes.
What is the correct way to test if an external script raises an exception?
If there is no error s will be 0:
from os import system
s=system("python tutorial.py")
assert s == 0
Or use subprocess:
from subprocess import PIPE,Popen
s = Popen(["python" ,"tutorial.py"],stderr=PIPE)
_,err = s.communicate() # err will be empty string if the program runs ok
assert not err
Your try/except is catching nothing from the tutorial file, you can move everything outside the it and it will behave the same:
from os import system
test_passes = False
s = system("python tutorial.py")
test_passes = True
assert test_passes
from os import system
test_passes = False
try:
system("python tutorial.py")
test_passes = True
except:
pass
finally:
assert test_passes
This is going to solve your problem.
Finally block is going to process if any error is raised. Check this for more information.It's usually using for file process if it's not with open() method, to see the file is safely closed.
This question already has answers here:
is there a pythonic way to try something up to a maximum number of times?
(10 answers)
Closed 7 months ago.
I am writing in Python 2.7 and encounter the following situation. I would like to try calling a function three times. If all three times raise errors, I will raise the last error I get. If any one of the calls succeed, I will quit trying and continue immediately.
Here is what I have right now:
output = None
error = None
for _e in range(3):
error = None
try:
print 'trial %d!' % (_e + 1)
output = trial_function()
except Exception as e:
error = e
if error is None:
break
if error is not None:
raise error
Is there a better snippet that achieve the same use case?
use decorator
from functools import wraps
def retry(times):
def wrapper_fn(f):
#wraps(f)
def new_wrapper(*args,**kwargs):
for i in range(times):
try:
print 'try %s' % (i + 1)
return f(*args,**kwargs)
except Exception as e:
error = e
raise error
return new_wrapper
return wrapper_fn
#retry(3)
def foo():
return 1/0;
print foo()
Here is one possible approach:
def attempt(func, times=3):
for _ in range(times):
try:
return func()
except Exception as err:
pass
raise err
A demo with a print statement in:
>>> attempt(lambda: 1/0)
Attempt 1
Attempt 2
Attempt 3
Traceback (most recent call last):
File "<pyshell#18>", line 1, in <module>
attempt(lambda: 1/0)
File "<pyshell#17>", line 8, in attempt
raise err
ZeroDivisionError: integer division or modulo by zero
If you're using Python 3.x and get an UnboundLocalError, you can adapt as follows:
def attempt(func, times=3):
to_raise = None
for _ in range(times):
try:
return func()
except Exception as err:
to_raise = err
raise to_raise
This is because the err is cleared at the end of the try statement; per the docs:
When an exception has been assigned using as target, it is cleared
at the end of the except clause.
Ignoring the debug output and the ancient Python dialect, this looks good. The only thing I would change is to put it into a function, you could then simply return the result of trial_function(). Also, the error = None then becomes unnecessary, including the associated checks. If the loop terminates, error must have been set, so you can just throw it. If you don't want a function, consider using else in combination with the for loop and breaking after the first result.
for i in range(3):
try:
result = foo()
break
except Exception as error:
pass
else:
raise error
use_somehow(result)
Of course, the suggestion to use a decorator for the function still holds. You can also apply this locally, the decorator syntax is only syntactic sugar after all:
# retry from powerfj's answer below
rfoo = retry(3)(foo)
result = rfoo()
Came across a clean way of doing the retries. There is a module called retry.
First install the module using
pip install retry
Then import the module in the code.
from retry import retry
Use #retry decorator above the method, We can pass the parameters to the decorator. Some of the parameters are tries , delay , Exception.
Example
from retry import retry
#retry(AssertionError, tries=3, delay=2)
def retryfunc():
try:
ret = False
assert ret, "Failed"
except Exception as ex:
print(ex)
raise ex
The above code asserts and fails everytime, but the retry decorator retries for 3 times with a delay of 2 seconds between retries. Also this only retries on Assertion failures since we have specified the error type as AssertionError on any other error the function wont retry.
I have a python project I'm working on whereby instead of print statements I call a function say() so I can print information while in development and log information during production. However, I often forget this and put print statements in the code by mistake. Is there anyway to have the python program read its own source, and exit() if it finds any print statements outside of the function say()?
This can be done using the ast module. The following code will find any calls of the print statement and also of the print() function in case you are on Python 3 or Python 2 with the print_function future.
import ast
class PrintFinder(ast.NodeVisitor):
def __init__(self):
self.prints_found = []
def visit_Print(self, node):
self.prints_found.append(node)
super(PrintFinder, self).generic_visit(node)
def visit_Call(self, node):
if getattr(node.func, 'id', None) == 'print':
self.prints_found.append(node)
super(PrintFinder, self).generic_visit(node)
def find_print_statements(filename):
with open(filename, 'r') as f:
tree = ast.parse(f.read())
parser = PrintFinder()
parser.visit(tree)
return parser.prints_found
print 'hi'
for node in find_print_statements(__file__):
print 'print statement on line %d' % node.lineno
The output of this example is:
hi
print statement on line 24
print statement on line 26
While I don't recommend doing this, if you really want to you could have the Python interpreter throw an error by redefining the print statement.
If using Python 3, simply put this near the beginning / top of your code:
print = None
If there are any print statements, you will get a TypeError: 'NoneType' object is not callable error.
If using Python 2.x, you might use the idea suggested in another answer to allow Python 2.x to have an overridable print statement.
from __future__ import print_function
print = None
Putting this together with your say() function, you could do something like:
print_original = print
print = None
def say(data):
print = print_original
# Your current `say()` code here, such as:
print(data) # Could just use `print_original` instead.
# Redefine print to make the statement inaccessible outside this function.
print = None
I am doing some practice problems from online with python and I have a question about how to stay in a script if an error is raised. For example, I want to read in values from prompt and compare them to a set integer value inside the script. The only problem is that when someone enters something other than a number 'int(value)' (ex. value = 'fs') raises an error and exits the script. I want to have it so if this happens I stay inside the script and ask for another value to be entered at the prompt.
Use try/except.
>>> while True:
... try:
... x = int(raw_input("Please enter a number: "))
... break
... except ValueError:
... print "Oops! That was no valid number. Try again..."
...
success = false
while not success:
try:
value = raw_input('please enter an integer')
int(value)
success = true
except:
pass
How about catching it?
try:
a = int('aaa')
except ValueError:
print('Still working')
Ah, you just want to catch the error (as long as it isn't final): see http://docs.python.org/tutorial/errors.html for details? Or are you looking for something else?
for this, you use try... except as explained in the python documentation
Read up on the try: except: idiom here
if you are doing it as a function you can do it as a decorator of the function
def retry(func):
def wrapper(*args,**kwargs):
while True:
try:
return func(*args,**kwargs)
except Exception as e:
print(f"{e} running again") # or simply pass
return wrapper
#retry
def myfunction():
if badthinghappend:
raise Error
return something