python: exception inside try doesn't jump to except - python

I am trying to search within the EU parliment votes' description.
They are standard xml files. So far I noticed 2 versions of the votes' result: where the description is text and where it is an url.
Fails at this file: https://www.europarl.europa.eu/doceo/document/PV-9-2022-09-12-RCV_FR.xml
Works fine on the following file: https://www.europarl.europa.eu/doceo/document/PV-9-2022-07-06-RCV_FR.xml
My problem is not the failure itself (that's why I added the try clause) but that code execution doesn't jump to the except path, just exits here with this: string indices must be integers
Please help, why isn't the error properly handled?
for currentfile in f:
mytree = ET.parse(xmlfiles + "\\" + currentfile)
myroot = mytree.getroot()
dixml = etree_to_dict(myroot)
for votes in dixml['PV.RollCallVoteResults']['RollCallVote.Result']:
try:
title = votes['RollCallVote.Description.Text'] #fails here
titletype = type(title)
if titletype == dict:
title=title['#text']
except :
title = votes['RollCallVote.Description.Text']['a']['#text']
try:
ltitle = title.lower()
except :
print(type(title))
if stringtosearch in ltitle:
print(title,currentfile)
edit:
full trace:
Message=string indices must be integers
Source=...debug.py
StackTrace:
File "...debug.py", line 44, in <module>
title = votes['RollCallVote.Description.Text']
During handling of the above exception, another exception occurred:
File "...debug.py", line 44, in <module>
title = votes['RollCallVote.Description.Text']
File "...debug.py", line 49, in <module> (Current frame)
title = votes['RollCallVote.Description.Text']['a']['#text']

This would happen if there is a new exception raised within your catch block, I would presume specifically the votes object at some point of you accessing it, raises this exception.
Try printing out votes and then each time you access it by indexing print it out you'll see to which extent you can continue accessing it via string index ( votes['string'] ).

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.

I am getting unbound local error while pickle loading a file

I am. Pickle loading two files one by one and I am getting an unbound local error while closing them.
I used exception handling while opening the file and in the except block it shows unbound local error while closing the files.
though i used filenotfound In the exception block as it is a necessary exception to handle.no indentation errors are there i just am not able to handle the error stating.
"Traceback (most recent call last):
File "d:\Python\t.py", line 648, in dispdeisel
fdl=open("D:/Python/deisel/"+str(z1)+".txt","rb+")
FileNotFoundError: [Errno 2] No such file or directory: 'D:/Python/deisel/Wed Apr 29 2020.txt'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "d:\Python\t.py", line 820, in <module>
b.dispdeisel()
File "d:\Python\t.py", line 664, in dispdeisel
fdl.close()
UnboundLocalError: local variable 'fdl' referenced before assignment"
k1=[]
try:
tdc=open("D:/Python/deisel/collection.txt","rb+")
fdl=open("D:/Python/deisel/"+str(z1)+".txt","rb+")
while True:
self.f1=pickle.load(tdc)
self.fd=pickle.load(fdl)
k1.append(self.f1)
kd.append(self.fd)
except EOFError and FileNotFoundError:
qa=0
for i in kd:
if "L"in i:
qa1=i[:-1]
qa=qa+int(qa)
else:
qa=qa+int(i[0])
print (" Total Collection for Deisel on date ",z1,"is",qa)
tdc.close()
fdl.close()
In your example code, when this line is reached (and causes an error):
tdc=open("D:/Python/deisel/collection.txt","rb+")
.. then the next line will never be executed and fdl won't have a value.
After the error, execution continues after except EOFError and FileNotFoundError: and this line is reached:
fdl.close()
Since fdl was never defined (as that line was skipped), it has no value and that's the cause of your error.
One way of fixing it would be to deal with the exceptions more cleanly:
class SomeClass:
def some_method(self, z1):
# initialisation
qa = 0
kd = []
k1 = []
try:
tdc = open("D:/Python/deisel/collection.txt","rb+")
try:
fdl = open("D:/Python/deisel/"+str(z1)+".txt","rb+")
try:
try:
while True:
self.f1 = pickle.load(tdc)
self.fd = pickle.load(fdl)
k1.append(self.f1)
kd.append(self.fd)
except EOFError:
pass # no message needed, but not the nicest way to use the exception
for i in kd:
if "L" in i:
# this bit makes no sense to me, but it's not relevant
qa1 = i[:-1]
qa = qa + int(qa)
else:
qa = qa + int(i[0])
print(" Total Collection for Deisel on date ", z1, "is", qa)
finally:
tdc.close()
fdl.close()
except FileNotFoundError:
tdc.close() # this is open, closing it
pass # some error message perhaps?
except FileNotFoundError:
pass # some error message perhaps?
This is better, but not very Pythonic and only illustrates how you could solve your problem - it's not at all how I recommend you write this.
Closer to what you probably need:
import pickle
class SomeClass:
def some_method(self, z1):
# initialisation
qa = 0
kd = []
k1 = []
try:
with open("D:/Python/deisel/collection.txt","rb+") as tdc:
try:
with open("D:/Python/deisel/"+str(z1)+".txt","rb+") as fdl:
try:
while True:
self.f1 = pickle.load(tdc)
self.fd = pickle.load(fdl)
k1.append(self.f1)
kd.append(self.fd)
except EOFError:
pass # no message needed, but not the nicest way to use the exception
for i in kd:
if "L" in i:
# this bit makes no sense to me, but it's not relevant
qa1 = i[:-1]
qa = qa + int(qa)
else:
qa = qa + int(i[0])
print(" Total Collection for Deisel on date ", z1, "is", qa)
except FileNotFoundError:
pass # some error message perhaps?
except FileNotFoundError:
pass # some error message perhaps?
with does exactly what you're trying to do and cleans up the file handle, guaranteed.
And this still has the issue of getting multiple pickles from files, with no guarantee the number of pickles will be the same for both - if you write these pickles yourself, why not pickle a list of objects and avoid that mess?
In general, don't use exceptions if you expect them to occur, instead code directly what you expect - it's easier to read and maintain and it generally performs better:
import pickle
from pathlib import Path
class SomeClass:
def some_method(self, z1):
# initialisation
qa = 0
kd = []
k1 = []
fn1 = "D:/Python/deisel/collection.txt"
fn2 = "D:/Python/deisel/"+str(z1)+".txt"
if not Path(fn1).is_file() or not Path(fn2).is_file():
return # some error message perhaps?
with open(fn1, "rb+") as tdc:
with open(fn2, "rb+") as fdl:
try:
while True:
# not using self.f1 and .fd, since it seems they are just local
# also: why are you loading k1 anyway, you're not using it?
k1.append(pickle.load(tdc))
kd.append(pickle.load(fdl))
except EOFError:
pass # no message needed, but not the nicest way to use the exception
for i in kd:
if "L" in i:
qa1 = i[:-1]
qa = qa + int(qa)
else:
qa = qa + int(i[0])
print(" Total Collection for Deisel on date ", z1, "is", qa)
I don't know about the rest of your code, but you could probably get rid of the EOF exception as well, if you pickle in a predictable way and it seems the load of f1 into k1 only serves the purpose of being a possible limit to how many elements are loaded from kd, which is wasteful.
Note how, with every example, the code gets more readable and shorter. Shorter by itself is not a good thing, but if your code becomes more easy to read and understand, performs better and is shorter on top, you know you're on the right track.

Python - try/except not working when variable assigned to sys.argv

I have this section in my code:
# I/O files
inp_arq = sys.argv[1]
out_arq = sys.argv[2]
pad_ref = "pad_ref03.fasta"
tes_mdl = "model_05_weights.best.hdf5"
and at the end:
try:
results_df.to_csv(out_arq,index = False)
print(f"File saved as: {out_arq}")
except IndexError:
print("No output file created")
If no file is passed in as out_arq (sys.argv[2]) it should run the script and print "No output file created" at the end. But I'm getting the "IndexError: list index out of range."
But if I comment out the "out_arq = sys.argv[2]" line and change the code to:
try:
results_df.to_csv(sys.argv[2],index = False)
print(f"File saved as: {sys.argv[2]}")
except IndexError:
print("No output file created")
It works and I got the message, but I'm not sure why. I'd like to have all my I/O file/vars at the begginig of the script, but with this one (out_arq) I can't.
How can I solve this? And why this happens?
If you look at the stack trace that is printed by the exception, you should see that the exception is raised on this line:
out_arq = sys.argv[2]
This is outside the try block, so the exception is not caught, and causes your program to terminate.
A solution is to check, before indexing the array, whether the element exists:
out_arq = sys.argv[2] if len(sys.argv) >= 3 else None
Then use if instead of try:
if out_arq:
results_df.to_csv(out_arq,index = False)
print(f"File saved as: {out_arq}")
else:
print("No output file created")

Attribute Error: 'NoneType' object has no attribute 'find'

I keep having issues when trying to run this code. Had some help but still not working. Please help :)
Full code :
#!/usr/bin/env python3
from __future__ import print_function
try:
import pymarketcap
import decimal
from operator import itemgetter
import argparse
except Exception as e:
print('Make sure to install {0} (pip3 install {0}).'.format(str(e).split("'")[1]))
exit()
# arguments and setup
parser = argparse.ArgumentParser()
parser.add_argument('-m','--minimum_vol',type=float,help='Minimum Percent volume per exchange to have to count',default=1)
parser.add_argument('-p','--pairs',nargs='*',default=[],help='Pairs the coins can be arbitraged with - default=all')
parser.add_argument('-c','--coins_shown',type=int,default=10,help='Number of coins to show')
parser.add_argument('-e','--exchanges',nargs='*',help='Acceptable Exchanges - default=all',default=[])
parser.add_argument('-s','--simple',help='Toggle off errors and settings',default=False,action="store_true")
args = parser.parse_args()
cmc = pymarketcap.Pymarketcap()
info = []
count = 1
lowercase_exchanges = [x.lower() for x in args.exchanges]
all_exchanges = not bool(args.exchanges)
all_trading_pairs = not bool(args.pairs)
coin_format = '{: <25} {: >6}% {: >10} {: >15} {: <10} {: <10} {: <15} {: <5}'
if not args.simple:
print('CURRENT SETTINGS\n* MINIMUM_PERCENT_VOL:{}\n* TRADING_PAIRS:{}\n* COINS_SHOWN:{}\n* EXCHANGES:{}\n* ALL_TRADING_PAIRS:{}\n* ALL_EXCHANGES:{}\n'.format(args.minimum_vol,args.pairs,args.coins_shown,lowercase_exchanges,all_trading_pairs,all_exchanges))
# retrieve coin data
for coin in cmc.ticker():
try:
markets = cmc.markets(coin["id"])
except Exception as e:
markets = cmc.markets(coin["symbol"])
best_price = 0
best_exchange = ''
best_pair = ''
worst_price = 999999
worst_exchange = ''
worst_pair = ''
has_markets = False
for market in markets:
trades_into = market["pair"].replace(str(coin["symbol"])," ").replace("-"," ")
if market['percent_volume'] >= args.minimum_vol and market['updated'] and (trades_into in args.pairs or all_trading_pairs) and (market['exchange'].lower() in lowercase_exchanges or all_exchanges):
has_markets = True
if market['price_usd'] >= best_price:
best_price = market['price_usd']
best_exchange = market['exchange']
best_pair = trades_into
if market['price_usd'] <= worst_price:
worst_price = market['price_usd']
worst_exchange = market['exchange']
worst_pair = trades_into
if has_markets:
info.append([coin['name'],round((best_price/worst_price-1)*100,2),worst_price,worst_exchange,worst_pair,best_price,best_exchange,best_pair])
elif not args.simple:
print(coin['name'],'had no markets that fit the criteria.')
print('[{}/100]'.format(count),end='\r')
count += 1
# show data
info = sorted(info,key=itemgetter(1))[::-1]
print(coin_format.format("COIN","CHANGE","BUY PRICE","BUY AT","BUY WITH","SELL PRICE","SELL AT","SELL WITH"))
for coin in info[0:args.coins_shown]:
print(coin_format.format(*coin))
I keep getting this 2 errors :
File "./run", line 33, in <module>
markets = cmc.markets(coin["id"])
File "/Users/alex/anaconda3/lib/python3.6/site-packages/pymarketcap/core.py", line 296, in markets
marks = html.find(id="markets-table").find("tbody").find_all('tr')
AttributeError: 'NoneType' object has no attribute 'find'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "./run", line 35, in <module>
markets = cmc.markets(coin["symbol"])
File "/Users/alex/anaconda3/lib/python3.6/site-packages/pymarketcap/core.py", line 296, in markets
marks = html.find(id="markets-table").find("tbody").find_all('tr')
AttributeError: 'NoneType' object has no attribute 'find'
Any help would be tremendously appreciated. Thank you
Received some great help before on my previous question but still no solution yet.
Any help would be tremendously appreciated. Thank you Received some great help before on my previous question but still no solution yet.
I think the issue is that, if for some coin there is just nothing to be found (no matter if you use coin["id"] or coin["symbol"]), which can be caused by dead links which are built into the ticker module (coinmarketcap.com/currencies/). In this case
markets = cmc.markets(coin["id"])
markets = cmc.markets(coin["symbol"])
will both throw an AttributeError. You should change your code to
for coin in cmc.ticker():
try:
# this call can fail
markets = cmc.markets(coin["id"])
except AttributeError as e:
try:
# second call could also fail
markets = cmc.markets(coin["symbol"])
except AttributeError as e1:
print("Nothing found for " + coin["id"])
continue #skip this coin?
best_price = 0
I tried your code and it failed for a coin called janus for which, when you try the link manually, a PageNotFound is displayed, which would explain why it doesn't work to.
NoneType means that instead of an instance of whatever Class or Object you think you're working with, you've actually got None. That usually means that an assignment or function call up above failed or returned an unexpected result.
For Further investigation, I'd suggest you to print the response and it's type of the following expression:
for coin in cmc.ticker():
try:
markets = cmc.markets(coin["id"])
except Exception as e:
markets = cmc.markets(coin["symbol"])
best_price = 0
print(markets)
print(type(markets))
This wont solve your problem, but might give you an insight of the Line of Code that is troubling you. And you can further debug it as to where you are getting it wrong. And if the problem persists, you can edit your question and post the further evaluated code/traceback call, which will help us(the community members) to help you in solving your problem.
Usually, there are data types in python which you cannot iterate through and might require to either typecast it in some way which is iterable(eg. Dictionaries, Lists) or use attributes to access a value at a given index in your case.
Hope it helps :)

Condition not being evaluated as expected

I have a piece of code that acts as a listener of a button and evaluates whether some fields above this button are filled in:
def goListener(self):
if all( [self.nme.get() != "", self.dsc.get() != "", self.imp.get != ""] ):
name = self.nme.get()
desc = self.dsc.get()
while True:
try:
imp = int(self.imp.get())
break
except:
imp = int(self.imp.get())
When I run this program with different fields filled in or otherwise, it gets it right and produces the error message I ask it to with every combination except where nme and dsc are filled in but imp isn't, this produces the error message:
Traceback (most recent call last):
File "C:\Python33\lib\tkinter\__init__.py", line 1442, in __call__
return self.func(*args)
File "C:\Python33\todo.py", line 68, in goListener
imp = int(self.imp.get())
ValueError: invalid literal for int() with base 10: ''
This is running the except block by the way, which it shouldn't. Is this a problem with the evaluation, or am I missing something here?
You have:
self.imp.get != ""
You are failing to invoke the .get() method. Try:
self.imp.get() != ""
If imp = int(self.imp.get()) throws an error, calling it again outside of a try block will throw the same error.
The except block is for code that should run when there is an exception:
try:
imp = int(self.imp.get())
break
except:
print "Something bad happened"

Categories

Resources