Python string indices must be integers - python

I'm reading a Dictionary from an API which has a field called 'price'.
I'm reading it fine for a while (so, the code works) until I get to a point I get the error message: string indices must be integers.
That breaks my code.
So, I would like to find a way to skip it (ignore it) when this happens, and continue with the code. And just print something out so I know something happened.
So, far I don't manage to see what number is causing this error.
If I test this by itself, it works fine.
fill = {'price': 0.00002781 }
price = fill['price'] # OUTPUT: string indices must be integers
print(price)
I've tried many things:
from decimal import Decimal
price = decimal(fill['price'])
also:
price = int(fill['price']) # but it's not really an int
and:
price = float(fill['price']) # but sometimes it's a very big float so I need decimal

It seems that what you get from the API is not exactly what you expect:
The variable fill is a string (at least at the time you get the error).
As strings can't have string indices (like dictionaries can) you get the TypeError exception.
To handle the exception and troubleshoot it, you can use try-except, like so:
try:
price = fill['price']
except TypeError as e:
print(f"fill: {fill}, exception: {str(e)}")
This way, when there is an issue, the fill value will be printed as well as the exception.

string indices must be integers tells you that the type of fill during runtime at some point is a str instead of Dict. I suggest that you add type checking or assertion to your program to make sure fill is of the expected type.

If you want to just ignore it you could use try and except blocks.
try:
price = fill['price']
except Exception as e:
print(f"Error reading the price. Error: {e}")

Related

How to read and understand 'Unexpected type(s)' problem in Python?

I am trying to split a String based on the symbol: | and further split each String in it on a : and convert the result into a dictionary as below.
column_data = 'component_id:numeric(15,0)|name:character varying(30)|operation_num:numeric(15,0)|component_item:numeric(15,0)|item_number:character varying(800)|last_update_date:timestamp without time zone|last_updated_by:numeric(15,0)|creation_date:timestamp without time zone|created_by:numeric(15,0)|item_num:numeric|component_quantity:numeric|component_yield_factor:numeric|component_remarks:character varying(240)|effectivity_date:date|change_notice:character varying(10)'
column_names = dict(item.split(":") for item in gp_column_data.split("|"))
But I see a warning on the IDE that says:
Unexpected type(s): (Generator[List[str], Any, None]) Possible types: (Mapping) (Iterable[Tuple[Any, Any]])
The image can be seen below:
The same logic worked fine on Python shell but when I put the logic on IDE, the line highlights.
gp_column_data is a str that I am receiving as a method parameter.
def fix_source_columns(gp_column_data: str, precision_columns:str):
column_names = dict(item.split(":") for item in gp_column_data.split("|"))
I am new to Python and see these messages often on IDE.
Could anyone let me know if this is an error message ? If so how can I fix the problem ?
The IDE is smart enough to warn you that item.split(":") might output an iterable with a single element in case item does not contain : (or more than 2 if there are multiple :). In these cases, dict will fail because it expects an iterable in which all elements have exactly 2 elements (which is exactly what Iterable[Tuple[Any, Any]] in the warning means).

Getting exception "openpyxl.utils.exceptions.IllegalCharacterError"

I am extracting data from an Oracle 11g Database using python and writing it to an Excel file. During extraction, I'm using a python list of tuples (each tuple indicates each row in dataset) and the openpyxl module to write the data into Excel. It's working fine for some datasets but for some, it's throwing the exception:
openpyxl.utils.exceptions.IllegalCharacterError
This is the solution I've already tried:
Openpyxl.utils.exceptions.IllegalcharacterError
Here is my Code:
for i in range(0,len(list)):
for j in range(0,len(header)):
worksheet_ntn.cell(row = i+2, column = j+1).value = list[i][j]
Here is the error message:
raise IllegalCharacterError
openpyxl.utils.exceptions.IllegalCharacterError
I did get this error because of some hex charactres in some of my strings.
'Suport\x1f_01'
The encode\decode solutions mess with the accente words too
So...
i resolve this with repr()
value = repr(value)
That give a safe representation, with quotation marks
And then i remove the first and last charactres
value = repr(value)[1:-1]
Now you can safe insert value on your cell
The exception tells you everything you need to know: you must replace the characters that cause the exception. This can be done using re.sub() but, seeing as only you can decide what you want to replace them with — spaces, empty strings, etc. — only you can do this.

iterate threw list and if value doesnt excist hide error and continue

I've got a List like:
results = ['SDV_GAMMA','SDV_BETA,'...','...']
and then comes and for loop like:
for i in range (len(results)):
a = instance.elementSets[results[i]]
The strings defined in the result-list are part of a *.odb result file and if they didn't exist there comes an error.
I would like that my program doesn't stop cause of an error. It should go on and check if values of the others result values exist.
So i do not have to sort every result before i start my program. If it´s not in the list, there is no problem, and if it exists i get my data.
I hope u know what i mean.
You can use try..except block
Ex:
for i in results
try:
a = instance.elementSets[results[i]]
except:
pass
You can simply check the presence of results[i] in instance.elementSets before extracting it.
If instance.elementSets is a dictionary, use the dict.get command.
https://docs.python.org/3/library/stdtypes.html#dict.get

Python: Append a parsed string but throw out non-compliant values?

Warning: I'm a total newbie; apologies if I didn't search for the right thing before submitting this question. I found lots on how to ignore errors, but nothing quite like what I'm trying to do here.
I have a simple script that I'm using to grab data off a database, parse some fields apart, and re-write the parsed values back to the database. Multiple users are submitting to the database according to a delimited template, but there is some degree of non-compliance, meaning sometimes the string won't contain all/any delimiters. My script needs to be able to handle those instances by throwing them out entirely.
I'm having trouble throwing out non-compliant strings, rather than just ignoring the errors they raise. When I've tried try-except-pass, I've ended up getting errors when my script attempts to append parsed values into the array I'm ultimately writing back to the db.
Originally, my script said:
def parse_comments(comments):
parts = comments.split("||")
if len(parts) < 20:
raise ValueError("Comment didn't have enough || delimiters")
return Result._make([parts[i].strip() for i in xrange(2, 21, 3)])
Fully compliant uploads would append Result to an array and write back to db.
I've tried try/except:
def parse_comments(comments):
parts = comments.split("||")
try:
Thing._make([parts[i].strip() for i in xrange(2, 21, 3)])
except:
pass
return Thing
But I end up getting an error when I try and append the parsed values to an array -- specifically TypeError: 'type' object has no attribute 'getitem'
I've also tried:
def parse_comments(comments):
parts = comments.split("||")
if len(parts) >= 20:
Thing._make([parts[i].strip() for i in xrange(2, 21, 3)])
else:
pass
return Thing
but to no avail.
tl;dr: I need to parse stuff and append parsed items. If a string can't be parsed how I want it, I want my code to ignore that string entirely and move on.
But I end up getting an error when I try and append the parsed values to an array -- specifically TypeError: 'type' object has no attribute 'getitem'
Because Thing means the Thing class itself, not an instance of that class.
You need to think more clearly about what you want to return when the data is invalid. It may be the case that you can't return anything directly usable here, so that the calling code has to explicitly check.
I am not sure I understand everything you want to do. But I think you are not catching the error at the right place. You said yourself that it arose when you wanted to append the value to an array. So maybe you should do:
try:
# append the parsed values to an array
except TypeError:
pass
You should give the exception type to catch after except, otherwise it will catch any exception, even a user's CTRL+C which raise a KeyboardInterrupt.

Python BeautifulSoup is unnecessarily slow

While this code works pretty fast:
for olay in soup("li", {"class":"textb"}):
tanim = olay("strong")
try:
print tanim[0]
except IndexError:
pass
Getting string property like this makes this code considerably slower:
for olay in soup("li", {"class":"textb"}):
tanim = olay("strong")
try:
print tanim[0].string
except IndexError:
pass
My question is, am I doing something that I shouldn't getting string property like that? Should I have used something else to get plain text version of an object?
Update:
This is also working pretty fast, so slowness is unique to string property I guess?
for olay in soup("li", {"class":"textb"}):
tanim = olay("strong")
try:
print tanim[0].text
except IndexError:
pass
If you just want to print the string representation of tanim[0]. You should just do: print str(tanim[0]). Also, do a dir(tanim[0]) to see if it has a property called string at all.
for olay in soup("li", {"class":"textb"}):
tanim = olay("strong")
try:
print str(tanim[0])
except IndexError:
pass
For everyone to provide a better answer, you could also post the target HTML or the URI and mention which bit you are trying to extract out of it.

Categories