How do I handle my own exceptions and get the excetion to run another prodcure?

4469
8
09-23-2011 07:38 AM
TimLangner
Occasional Contributor III
Hi there

I'm attempting to run a script in Python 2.6 referencing ArcGIS 10. I got the script to run but then I decided to use the try and except method and handle multiple exceptions.

However as soon as I started doing this I'm getting the following error:
except EXCEPTION:
NameError: global name 'EXCEPTION' is not defined
I think I need to define a class but I'm not sure how that would relate to then running an additional procedure. The idea of the programme is to create a backup of 3 feature classes and if errors occur, pass them to the error exception procedure. This then prints an error message and calls the procedure to restart the map services.

The section of code is as follows:

  print "\n5. Now renameing " + TABLE_OWNER + SDE_FC_CURRENT + " to " + TABLE_OWNER + SDE_FC_BACKUP + " providing no lock exists"
  try:
    try:
      if arcpy.Exists(TABLE_OWNER + SDE_FC_CURRENT) ==1:
        arcpy.Rename_management (TABLE_OWNER + SDE_FC_CURRENT,
                                 TABLE_OWNER + SDE_FC_BACKUP)
      print "test " + EXCEPTION
    except EXCEPTION:
      if arcpy.TestSchemaLock(TABLE_OWNER + SDE_FC_CURRENT) ==0:
        EXCEPTION(LOCK_ERROR_TEXT, SDE_FC_CURRENT)
    except LOCK_ON_BACKUP:
      if arcpy.TestSchemaLock(TABLE_OWNER + SDE_FC_BACKUP) ==0:
        EXCEPTION(LOCK_ERROR_TEXT, SDE_FC_BACKUP)
  except UNKNOWN_ERROR2:
    if arcpy.Exists(TABLE_OWNER + SDE_FC_CURRENT) ==0:
      EXCEPTION(UNKNOWN_ERROR, SDE_FC_CURRENT + " and " + SDE_FC_BACKUP)
I hope that is enough code. I can supply more if required.

Kind regards

Tim
Tags (2)
0 Kudos
8 Replies
ChrisBater
New Contributor II
Have you checked this page out?

http://docs.python.org/tutorial/errors.html
0 Kudos
StacyRendall1
Occasional Contributor III
I don't know what the rest of your code looks like, but I'm not sure I get exactly what you are trying to do (you seem to want to raise and handle your exception in the same place).

You will need to define your own Exception class, and then a module that raises the exception if something goes wrong, then the place that calls that module must be within a try...except statement which handles the exception. Here is a simple example of the most trivial error raising program; which will catch some common errors when attempting to read a text file:
import os

class fileLoaderErrors(Exception):
 '''error handling; error code:
 0 - path doesn't exist
 1 - extension isn't correct
 '''
 def __init__(self, errorCode, filePath):
  self.errorCode = errorCode
  self.filePath = filePath
 def __str__(self):
  if self.errorCode == 0:
   errorStr =  'File does not exist at specified path: %s' % self.filePath
  elif self.errorCode == 1:
   errorStr = 'File extension is not correct, .txt is required, file provided: %s' % self.filePath
  else:
   errorStr = 'Unknown error with %s' % self.filePath 
  return errorStr


def fileOpener(filePath):
 '''stupid little module to load a file if it exists and the extension is correct, otherwise throw an exception'''
 if os.path.exists(filePath):  
  if filePath.find('.txt') != -1: 
   return open(filePath)  
  else:
   raise fileLoaderErrors(1, filePath) 
 else:
  raise fileLoaderErrors(0, filePath)


if __name__ == "__main__":
 path = 'D:\\Temp\\new2.txt'
 try:
  fObj = fileOpener(path)
 except fileLoaderErrors: # if there is an error, couln't load file...
  print 'Unable to load file: %s' % path
  fObj = None
 
 if fObj is not None: # if could open file, print contents and close...
  for line in fObj:
   print line
  fObj.close()


Notice that because I am catching my custom exception from the module it doesn't matter what the error message was, the program will go on to do its thing. This, however, won't catch other exceptions (such as forgetting the import os line at the top of the script).

Here is the code for what I think you are trying to do:
class LockError(Exception):
 def __init__(self, file):
  self.file = file
 def __str__(self):
  return  'Error: could not obtain lock on %s' % (self.file)

class UnknownError(Exception):
 def __init__(self, file):
  self.file = file
 def __str__(self):
  return  'Error: %s does not exist %s' % (self.file)

  
def fileRenamer(TABLE_OWNER, SDE_FC_CURRENT, SDE_FC_BACKUP):
 print "\n5. Now renaming " + TABLE_OWNER + SDE_FC_CURRENT + " to " + TABLE_OWNER + SDE_FC_BACKUP + " providing no lock exists"

 if arcpy.Exists(TABLE_OWNER + SDE_FC_CURRENT) : # test if CURRENT exists
  
  if arcpy.TestSchemaLock(TABLE_OWNER + SDE_FC_CURRENT)  and arcpy.TestSchemaLock(TABLE_OWNER + SDE_FC_BACKUP) : # test locking both
   arcpy.Rename_management (TABLE_OWNER + SDE_FC_CURRENT, TABLE_OWNER + SDE_FC_BACKUP) # perform rename
  
  elif not arcpy.TestSchemaLock(TABLE_OWNER + SDE_FC_CURRENT) : # if CURRENT couldn't be locked, raise the exception
   raise LockError(SDE_FC_CURRENT)
  
  elif not arcpy.TestSchemaLock(TABLE_OWNER + SDE_FC_BACKUP) : # if it was BACKUP that couldn't be locked, raise the exception
   raise LockError(SDE_FC_BACKUP)
   
 elif not arcpy.Exists(TABLE_OWNER + SDE_FC_CURRENT) : # CURRENT doesn't exist, raise the exception
  raise UnknownError(SDE_FC_CURRENT)

  
if __name__ == "__main__":
 table_owner = '...'
 sde_fc_current = '...'
 sde_fc_backup = '...'
 fileRenamer(table_owner, sde_fc_current, sde_fc_backup)

which will trow exceptions (displaying the relevant error messages).

In reality you want to handle those exceptions as well, so you will need to replace the last line with these lines:
try:
 fileRenamer(table_owner, sde_fc_current, sde_fc_backup)
except LockError: # if it has the lock error
 print 'Error obtaining lock on one of the data-sets during backup, attempting something else...'
 # Doing something else goes here...
except UnknownError: # if it was the unknown error
 print 'Error with CURRENT SDE - it does not exist'
 # Do something else here, or whatever...


You may even want to create different exceptions, depending on if it is the CURRENT or BACKUP features which is locked...

Let me know how you get on!
0 Kudos
TimLangner
Occasional Contributor III
Thanks for your reply Stacy.

I will study what you have written closely.

I'm trying to handle all my exceptions in their own procedure. So each type of error goes to the procedure, which is a standard procedure that prints an error message and then restarts all the map services.

I'm not 100% certain how the class and def __init__ works. I've seen various bits of code but I guess the issue is I don't understand what __init__ means theoretically for Python and thus I don't understand how to use it. Lots of places give the theoretical code for exceptions and then an example but not necessarily the meaning behind the code. However I'm now browsing the term __init__ and that should greatly help me.

I wasn't expecting to get into this area so quickly. I'll probably buy a book on python but right now I don't have time to wait for one to turn up. Would be great if ESRI published one. The section in ModelBuilder is far to short. They need something like the Apress book for Oracle Spatial, which I own and found extremely useful when completing my masters dissertation. Expect when I wanted to add an obsolete Ordnance Survey project into Oracle that is......

Kind regards

Tim
0 Kudos
TimLangner
Occasional Contributor III
Hi there

I've read through various web sites and Stacys helpful reply. However if I implement Stacys code then only an error message is displayed. However whilst I need an error message, I also need some code to run that brings up the map services after the error message is displayed or just before, if it can't be after.

I've got the code to bring up the map services but I am not sure how I call this via an exception as all the exceptions I've seen, seem to just print an error message and do nothing else afterwards. I know how to do this in PL/SQL but this is different way of working to that and I can't figure it out.

Kind regards

Tim
0 Kudos
TimLangner
Occasional Contributor III
Hi there

Sorry I rewrote my message when I read though it again. It seems I can call something else but I don't do it in the same place as the error exception handling, In PL/SQL I could call a procedure a raise but in Python, you call an exception and then do something else after the exception has been called. So they are separate parts of code.

Kind regards

Tim
0 Kudos
StacyRendall1
Occasional Contributor III
Hey Tim,

I don't know much about the theory behind classes, but I did a bit of GUI stuff in Python at one stage, and they rely pretty heavily on classes. As a result I kind of got my head around how to use them, if not exactly why...

The __init__ part runs when the class is first called (initialized); here it just maps the inputs to local variables (things starting with self). It is not particularly meaningful in this instance, and perhaps not even necessary, but all the examples I found seem to it... The __str__ part defines the string to return. Python will perform different actions depending on the type of class; so I guess an exception class does the __init__ then the __str__ all at once when called. If you have other functions within the class, they must be explicitly called. Other classes often work like this (entered at the command line, give it a go):
>>> class myClass():
...     def __init__(self):
...         print "class initialised..."
...     def myDef(self, arg):
...         return "function called with: %s " % (arg)
...
>>> c = myClass()
class initialised...
>>> c.myDef('Hello')
'function called with: Hello'


Anyway, I think what you need to do is have your restart map servers command in a function that is called if your rename (or whatever) function raises an exception...
0 Kudos
TimLangner
Occasional Contributor III
Hi Stancy,

Thank you for your reply. I solved the problem in the end.

In an exception statement I can have multiple if and else statements, which I can use to trap my exceptions and call the procedures that I have written to handle them. Thus I don't need to create my own exception classes.

This is a simpler solution and works for the time scale I have. May be one day I'll have time to get my head about creating my own exceptions.

Kind regards

Tim
0 Kudos
StacyRendall1
Occasional Contributor III
Great news; good luck!
0 Kudos