Distributed system: Raise error thrown on server side on client side - python

I have just started to create a distributed system that now got a single server and a bunch of clients. The language used is python and communication is done using sockets and JSON. When an error occurs on the server-side I send the error class-name and the error arguments to the client-side like this:
except Exception as e:
jsonResult = {"error":
{
"name":e.__class__.__name__,
"args": e.args
}
}
jsonResult = json.dumps(jsonResult)
jsonResult += "\n"
return jsonResult
And then try to raise it on the client-side like this:
errorFunc = decodedReply["error"]["name"]
args = decodedReply["error"]["args"]
print (args)
# Builds and appends the argumentstring to the error class-name.
errorFunc += '('
for arg in args:
# Handles when the argument is a string.
if isinstance(arg, str):
errorFunc += '\'' + arg + '\','
else:
errorFunc += arg + ','
# Removes the extra ',' from the string before adding the last ')'.
errorFunc = errorFunc[:-1]
errorFunc += ')'
# Debugging print.
print ("Here: " + errorFunc)
raise exec(errorFunc)
When I do this I get the error
TypeError: exceptions must derive from BaseException
From what I read here: Error exception must derive from BaseException even when it does (Python 2.7)
it looks like I have to declare it as a class. Is there anyway to get around that?

According to python you are raising something which is not an exception:
>>> type(exec("ValueError('ABC')"))
<class 'NoneType'>
You need to rewrite your code to have this:
>>> errorFunc = "ValueError('ABC')"
>>> exec('raise ' + errorFunc)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
ValueError: ABC

Related

Handle KeyError exception and get dictionary name which caused the trouble

KeyError exception object contains args attribute. This is a list and it contains a key name which user tries to access within a dictionary.
Is it possible to figure out dictionary name which does not contain that key and which caused an exception while trying to access the key within it?
Example
data = {"my_key": "my_value"}
try:
data["unknown_key"] except KeyError as e:
print("key name: ", e.args[0])
print("dictionary name: ", e.???) # Here I would need to know the the name of a variable which stores the dictionary is "data"
You can kinda hack this with Python 3.11+, since the traceback contains fine-grained information about where the error happened.
import ast
import linecache
import traceback
data = {"my_key": "my_value"}
flurk = data
try:
data["flep"] = data["my_key"] + flurk["unknown_key"]
except KeyError as e:
# Find the last frame where the exception occurred, formatted as a FrameSummary
err_frame = traceback.TracebackException.from_exception(e).stack[-1]
if err_frame.lineno == getattr(err_frame, "end_lineno", -1): # If we can reliably find the line,
# ... read the line,
line = linecache.getline(err_frame.filename, err_frame.lineno)
# find the "marked segment" in it,
fragment = line[err_frame.colno:err_frame.end_colno]
# ... and parse it as an expression.
expr: ast.Expression = ast.parse(fragment, mode='eval')
# Check we're dealing with a subscript (index) node...
assert isinstance(expr.body, ast.Subscript)
# ... and extract the main parts of the expression.
subscriptee = ast.unparse(expr.body.value)
subscript = ast.unparse(expr.body.slice)
else:
subscriptee = None # No idea
subscript = e.args[0] # Just use the exception message
raise RuntimeError(f"KeyError with {subscriptee=!r}, {subscript=!r}") from e
prints out
Traceback (most recent call last):
File "scratch_679.py", line 8, in <module>
data["flep"] = data["my_key"] + flurk["unknown_key"]
~~~~~^^^^^^^^^^^^^^^
KeyError: 'unknown_key'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "scratch_679.py", line 27, in <module>
raise RuntimeError(f"KeyError with {subscriptee=!r}, {subscript=!r}") from e
RuntimeError: KeyError with subscriptee='flurk', subscript="'unknown_key'"
so you can see the subscriptee name is flurk.

Handling key error in python

The below function parses the cisco command output,stores the output in dictionary and returns the value for a given key. This function works as expected when the dictionary contains the output. However, if the command returns no output at all the length of dictionary is 0 and the function returns a key error . I have used exception KeyError: But this doesn't seem to work.
from qa.ssh import Ssh
import re
class crypto:
def __init__(self, username, ip, password, machinetype):
self.user_name = username
self.ip_address = ip
self.pass_word = password
self.machine_type = machinetype
self.router_ssh = Ssh(ip=self.ip_address,
user=self.user_name,
password=self.pass_word,
machine_type=self.machine_type
)
def session_status(self, interface):
command = 'show crypto session interface '+interface
result = self.router_ssh.cmd(command)
try:
resultDict = dict(map(str.strip, line.split(':', 1))
for line in result.split('\n') if ':' in line)
return resultDict
except KeyError:
return False
test script :
obj = crypto('uname', 'ipaddr', 'password', 'router')
out = obj.session_status('tunnel0')
status = out['Peer']
print(status)
Error
Traceback (most recent call last):
File "./test_parser.py", line 16, in <module>
status = out['Peer']
KeyError: 'Peer'
The KeyError did not happend in the function session_status,it is happend in your script at status = out['Peer'].So your try and except in session_status will not work.you should make a try and except for status = out['Peer']:
try:
status = out['Peer']
except KeyError:
print 'no Peer'
or :
status = out.get('Peer', None)
Your exception is not in the right place. As you said you just return an empty dictionary with your function. The exception is trying to lookup the key on empty dictionary object that is returned status = outertunnel['Peer']. It might be easier to check it with the dict get function. status = outertunnel.get('Peer',False) or improve the test within the function session_status, like testing the length to decide what to return False if len(resultDict) == 0
This explains the problem you're seeing.
The exception happens when you reference out['Peer'] because out is an empty dict. To see where the KeyError exception can come into play, this is how it operates on an empty dict:
out = {}
status = out['Peer']
Throws the error you're seeing. The following shows how to deal with an unfound key in out:
out = {}
try:
status = out['Peer']
except KeyError:
status = False
print('The key you asked for is not here status has been set to False')
Even if the returned object was False, out['Peer'] still fails:
>>> out = False
>>> out['Peer']
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
out['Peer']
TypeError: 'bool' object is not subscriptable
I'm not sure how you should proceed, but dealing with the result of session_status not having the values you need is the way forward, and the try: except: block inside the session_status function isn't doing anything at the moment.

Python pyparsing issue

I am very new to python and using pyparsing but getting some exception with following code
while site_contents.find('---', line_end) != line_end + 2:
cut_start = site_contents.find(" ", site_contents.find("\r\n", start))
cut_end = site_contents.find(" ", cut_start+1)
line_end = site_contents.find("\r\n", cut_end)
name = site_contents[cut_start:cut_end].strip()
float_num = Word(nums + '.').setParseAction(lambda t:float(t[0]))
nonempty_line = Literal(name) + Word(nums+',') + float_num + Suppress(Literal('-')) + float_num * 2
empty_line = Literal(name) + Literal('-')
line = nonempty_line | empty_line
parsed = line.parseString(site_contents[cut_start:line_end])
start = line_end
Exception
Traceback (most recent call last):
File "D:\Ecllipse_Python\HellloWorld\src\HelloPython.py", line 108, in <module>
parsed = line.parseString(site_contents[cut_start:line_end]) # parse line of data following cut name
File "C:\Users\arbatra\AppData\Local\Continuum\Anaconda\lib\site-packages\pyparsing.py", line 1041, in parseString
raise exc
pyparsing.ParseException: Expected W:(0123...) (at char 38), (line:1, col:39)
how to resolve this issue?
You'll get a little better exception message if you give names to your expressions, using setName. From the "Expected W:(0123...)" part of the exception message, it looks like the parser is not finding a numeric value where it is expected. But the default name is not showing us enough to know which type of numeric field is expected. Modify your parser to add setName as shown below, and also change the defintion of nonempty_line:
float_num = Word(nums + '.').setParseAction(lambda t:float(t[0])).setName("float_num")
integer_with_commas = Word(nums + ',').setName("int_with_commas")
nonempty_line = Literal(name) + integer_with_commas + float_num + Suppress(Literal('-')) + float_num * 2
I would also preface the call to parseString with:
print site_contents[cut_start:line_end]
at least while you are debugging. Then you can compare the string being parsed with the error message, including the column number where the parse error is occurring, as given in your posted example as "(at char 38), (line:1, col:39)". "char xx" starts with the first character as "char 0"; "col:xx" starts with the first column as "col:1".
These code changes might help you pinpoint your problem:
print "12345678901234567890123456789012345678901234567890"
print site_contents[cut_start:line_end]
try:
parsed = line.parseString(site_contents[cut_start:line_end])
except ParseException as pe:
print pe.loc*' ' + '^'
print pe
Be sure to run this in a window that uses a monospaced font (so that all the character columns line up, and all characters are the same width as each other).
Once you've done this, you may have enough information to fix the problem yourself, or you'll have some better output to edit into your original question so we can help you better.

Python throws exception on bypassing True as method parameter

I have the following concern - Why does the following code throw exception on param2?:
def paramcheck(param1, param2):
try:
if param1:
print('param1: ' + param1)
if param2:
print('param2: ' + param2)
except:
print('error')
paramcheck(False, True)
I'm using python 3.4.
Thanks!
If you hadn't quashed the error message you would have gotten a helpful message:
>>> param1 = True
>>> print('param1: ' + param1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'bool' objects
As the error says, you can't concatenate strings with booleans in Python. You have to convert the boolean manually:
print('param1: ' + str(param1))
Or you can use formatting operators:
print('param1: %s' % (param1,))
print('param1: {}'.format(param1))

Python:winreg module :Windows 7:None is not valid HKEY error

I ran into issues while reading registry value for windows 7 winth winreg module .Any pointers to resolve the same?
Code :
try:
ParentKey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall")
i = 0
while 1:
name, value, type = _winreg.EnumValue(ParentKey, i)
print repr(name),
i += 1
except Exception as e:
print(Exception(e))
ParentKey =_winreg.DisableReflectionKey(ParentKey)
temp = _winreg.QueryValueEx(ParentKey, 'DisplayName')
temp1 = _winreg.QueryValueEx(ParentKey, 'DisplayVersion')
temp2 = _winreg.QueryValueEx(ParentKey, 'Publisher')
temp3 = _winreg.QueryValueEx(ParentKey, 'InstallLocation')
display = str(temp[0])
display_ver=str(temp1[0])
display_p=str(temp2[0])
display_loc=str(temp3)
print ('Display Name: ' + display + '\nDisplay version: ' + display_ver + '\nVendor/Publisher: ' + display_p +'\nRegkey: ' + display_loc +'\nInstall Location: ' )
Output:
[Error 259] No more data is available
Traceback (most recent call last):
File "C:\Users\Test\workspace\Pythontests\src\test.py", line 24, in <module>
temp = _winreg.QueryValueEx(ParentKey, 'DisplayName')
TypeError: None is not a valid HKEY in this context
**strong text**
This line:
ParentKey = _winreg.DisableReflectionKey(ParentKey)
will return None. The function DisableReflectionKey is not documented as returning anything (success or failure is indicated by whether or not an exception is raised). Such a function that does not return anything returns None implicitly. Since you bind the returned value to ParentKey, that variable will holds None from that point on.
So, of course the subsequent call,
_winreg.QueryValueEx(ParentKey, 'DisplayName')
will fail since QueryValueEx requires a defined key (not None) to work.

Categories

Resources