Someone recently said to me "In Python it is better to try and ask for forgiveness later instead of begging for permission" which I found quite funny but also relates to my question
I'm creating a personal assistant of sorts called Ada and was being pedantic about performance. From what I gather, using a try statement is faster when it works then checking and then executing. E.G: (The second one being slower if the directory DOESNT EXIST???)
import os
try:
os.makedirs("Test")
except FileExistsError:
pass
# VS
if not os.path.exists("Test"):
os.makedirs("Test")
So when creating coding, you need to weigh up whats more likely. In my example it would be the file is more likely to NOT exist so I should use a try block which yields better performance then an If-Else
I was wondering if this is of any benefit to try (pun intended) this method of the default If-Else?
P.S (This question isn't a duplicate of Python if vs try-except since that's not specifying about comparing the probabilities of the try: code block)
My current code if anyone's interested: (Created a folder in AppData called Ada where a Config.ini file is made)
import os
AppDataDirectory = os.getenv("AppData")
AdaDirectory = AppDataDirectory + "\Ada"
ConfigFile = AdaDirectory + "\CONFIG.ini"
try:
File = open(ConfigFile, "r")
except FileNotFoundError:
try:
os.makedirs(AdaDirectory)
except FileExistsError:
print("Config File Missing")
# Setup Config File
The performance of try vs. if-else depends.
Generally, it is considered more pythonic to use try blocks because:
You do an action
If it fails then do something else
The benefit here is that if the action fails you can specify an exact error and react accordingly or keep the exception at the Base Exception class.
Using if-else isn't necessarily non-pythonic but with them python (this gets longer if there are elif statements),
Checks the boolean value of a statement
If boolean value is desired, then perform another action
If boolean value is not desired then do something else
Ultimately try blocks are recommended because you do something and specify an exact response if the action fails as opposed to setting up a variety of conditions.
A real time use case example of try-catch && if-else with Django:
I created a custom user model in account app. So if i try to import it from default user model like.
from django.contrib.auth.models import User
I will get a error like:
AttributeError: Manager isn't available; 'auth.User' has been swapped for 'account.User
and this will hang the process.
#from account.models import User # this is the correct import
if User.objects.filter(username="milon").exits():
print(f"Super User with username {env('SUPER_USER_NAME')} is already exit!!")
else:
superuser = User.objects.create_superuser(
username="milon", email="alim.abdul#gmail.com", password="******")
superuser.save()
But if I use try-catch block.
try:
superuser = User.objects.create_superuser(
username="milon"), email="alim.abdul#gmail.com", password="******")
superuser.save()
except IntegrityError:
print(f"Super User with username {env('SUPER_USER_NAME')} is already exit!!")
except Exception as e:
print(e)
We will get bellow error and this will not hang the process.
Manager isn't available; 'auth.User' has been swapped for 'account.User'
This example was tried in docker where i was used django & react separate project in docker container. For if-else docker was hanged the other processes. But using try-catch others process was not hanged in docker container.
Related
So, we had instance in the past where code were broken in IOT devices because of syntax errors.
While there is exception handling in the code. I wanted to create a script to check and make sure that the codes compiles and run without syntax error, else the script replace the broken code by an earlier version.
I tried this
from delta_script import get_update
def test_function():
try:
get_update()
except SyntaxError as syntaxError:
replace_script("utility.py", syntaxError)
except Exception as ignored:
pass
However the problem it when it hit a SyntaxError, it just throw it on the screen and replace_script
because the exception happens on delta_script.py from which get_update() was imported.
So what's the solution in this case?
I have also another function
def compile():
try:
for file in compile_list:
py_compile.compile(file)
except Exception as exception:
script_heal(file, exception)
however in this one, it never report any exception, because I go and introduce syntaxError and the code still compile without reporting an error
Any one could help me figure out a better way to solve those two problems?
thanks,
SyntaxErrors occur at compile time, not run time, so you generally can't catch them. There are exceptions, involving run time compilation using eval/exec, but in general, except SyntaxError: is nonsensical; something goes wrong compiling the code before it can run the code that sets up the try/except to catch the error.
The solution is to not write syntactically invalid code, or if you must write it (e.g. to allow newer Python syntax only when supported) to evaluate strings of said code dynamically with eval (often wrapping compile if you need something more complicated than a single expression) or exec.
This may have been asked before or I may be overly pedantic, but my own searches have come up empty.
Looking through the Python 2.x exceptions page, I'm not sure which one I should raise if my script determines that the __version__ of a module that's been imported, e.g. cv2, is not the correct version. For example, a script I'm working on requires OpenCV version 3; what's the best exception to raise in the following block if it determines that the version != 3?
import cv2
if not cv2.__version__.startswith('3'):
raise ValueError('OpenCV _3_ required')
You can create you own custom exception if the existing ones don't suffice.
class VersionError(Exception):
def __init__(self, msg):
Exception.__init__(self,msg)
You've got a lot of options depending on what you want to do with this exception... Generally, I'd expect the install scripts to handle setting up the appropriate versions of dependencies so I might think of this as a simple runtime assertion -- Therefore AssertionError may be appropriate.
This one is really nice -- You don't need an if statement, just an assert:
assert cv2.__version__.startswith('3'), 'OpenCV _3_ required'
My next bet would be to use RuntimeError as that is really meant to be a general exception that happens at runtime (and isn't usually meant to be caught)... It's a pretty general "Oh snap, something bad happened that we cannot recover from. Lets just spit out an error to let the user know what happened".
I'm trying to write to a file like this:
with open(filename), 'wb') as f:
f.write(data)
But when opening a file and writing to it many things might go wrong and I want to properly report what went wrong to the user. So I don't want to do:
try:
with open(filename), 'wb') as f:
f.write(data)
except:
print("something went wrong")
But instead I want to tell the user more specifics so that they can fix the problem on their end. So I started with catching the PermissionError to tell the user to fix their permissions. But soon I got a bugreport that the program would fail if filename pointed to a directory, so I also caught and reported the IsADirectoryError. But this is not all - it might be that the path to filename doesn't exist, so later I also added the FileNotFoundError.
Opening a file and writing to it is a very simple pattern but still many things can go wrong. I'm wondering whether there is an easy recipe that allows me to catch these errors and report them properly without giving a generic "some error happened" message. This kind of pattern has been used for decades, so there must be some list of things to check for, no?
I now caught a number of exceptions but I can imagine that even more are lurking around. Things probably become even worse when running this on non-Linux platforms...
What are the best practices for opening a file and writing to it in Python that give a maximum of information back to the user when things go wrong without ressorting to dumping the bare traceback?
On the operating system level there are only so many things that can go wrong when doing an open() and write() system call so there must exist a complete list?
You could catch the higher level exception OSError and then present the value of the strerror field to the user as the explanation. This relies on the fact that exceptions such as FileNotFoundError are subclasses of OSError and these subclasses can all be caught by using the base class.
Here's an example:
try:
filename = 'missing_file'
with open(filename) as f:
for line in f:
# whatever....
pass
except OSError as exc:
print('{!r}: {}'.format(filename, exc.strerror))
Running this code when missing_file does not exist produces this error message:
'missing_file': No such file or directory
Is anyone familiar with DRAKON?
I quite like the idea of the DRAKON visual editor and have been playing with it using Python -- more info: http://drakon-editor.sourceforge.net/python/python.html
The only thing I've had a problem with so far is python's try: except: exceptions. The only way I've attempted it is to use branches and then define try: and except: as separate actions below the branch. The only thing with this is that DRAKON doesn't pick up the try: and automatically indent the exception code afterwards.
Is there any way to handle try: except: in a visual way in DRAKON, or perhaps you've heard of another similar visual editor project for python?
Thanks.
You could put the whole "try: except:" construct inside one "Action" icon like this:
Both spaces and tabs can be used for indentation inside an icon.
There are limitation exist in Drakon since it is a code generator, but what you can do is to re-factor the code as much as possible and stuff it inside action block:
try:
function_1()
function_2()
except:
function_3()
Drakon works best if you follow suggested rules(skewer,happy route,branching etc).
Once you construct algorithm base on this, it can help you solve complex problems fast.
Hope thats help.
This may be an open ended or awkward question, but I find myself running into more and more exception handling concerns where I do not know the "best" approach in handling them.
Python's logging module raises an IOError if you try to configure a FileHandler with a file that does not exist. The module does not handle this exception, but simply raises it. Often times, it is that the path to the file does not exist (and therefore the file does not exist), so we must create the directories along the path if we want to handle the exception and continue.
I want my application to properly handle this error, as every user has asked why we don't make the proper directory for them.
The way I have decided to handle this can be seen below.
done = False
while not done:
try:
# Configure logging based on a config file
# if a filehandler's full path to file does not exist, it raises an IOError
logging.config.fileConfig(filename)
except IOError as e:
if e.args[0] == 2 and e.filename:
# If we catch the IOError, we can see if it is a "does not exist" error
# and try to recover by making the directories
print "Most likely the full path to the file does not exist, so we can try and make it"
fp = e.filename[:e.rfind("/")]
# See http://stackoverflow.com/questions/273192/python-best-way-to-create-directory-if-it-doesnt-exist-for-file-write#273208 for why I don't just leap
if not os.path.exists(fp):
os.makedirs(fp)
else:
print "Most likely some other error...let's just reraise for now"
raise
else:
done = True
I need to loop (or recurse I suppose) since there is N FileHandlers that need to be configured and therefore N IOErrors that need to be raised and corrected for this scenario.
Is this the proper way to do this? Is there a better, more Pythonic way, that I don't know of or may not understand?
This is not something specific to the logging module: in general, Python code does not automatically create intermediate directories for you automatically; you need to do this explicitly using os.makedirs(), typically like this:
if not os.path.exists(dirname):
os.makedirs(dirname)
You can replace the standard FileHandler provided by logging with a subclass which does the checks you need and, when necessary, creates the directory for the logging file using os.makedirs(). Then you can specify this handler in the config file instead of the standard handler.
Assuming it only needs to be done once at the beginning of your app's execution, I would just os.makedirs() all the needed directories without checking for their existence first or even waiting for the logging module to raise an error. If you then you get an error trying to start a logger, you can just handle it the way you likely already did: print an error, disable the logger. You went above and beyond just by trying to create the directory. If the user gave you bogus information, you're no worse off than you are now, and you're better in the vast majority of cases.