result = []
try:
for i in range(len(ass)):
int(df['sku'][i])
except ValueError:
result.append(df['sku'][i])
I need to collect all the errors in a list. Tell me, please, the code above adds only the first error, I need everything.
After iterating over all sku values, only those that cannot be converted to int should be included in the list.
You can move the try...except inside the loop:
result = []
for i in range(len(ass)):
try:
int(df['sku'][i])
except ValueError:
result.append(df['sku'][i])
You can also use isdigit() with a list comprehension as follows:
result = [val for val in df['sku'] if val.isdigit()]
However, you should note that isdigit() will not work in some cases e.g. those with leading signs.
As an example, '+1' will convert to an integer type fine with int() but will return False with is isdigit(). Similarly, -1 will convert fine with int() but return False with isdigit().
Further information can be found int the documentation:
str.isdigit()
Return true if all characters in the string are digits and there is at least one character, false otherwise.
You'd want the try-except in the loop:
result = []
for i in range(len(ass)):
try:
int(df['sku'][i])
except ValueError:
result.append(df['sku'][i])
But if it's really a list of non-digit SKUs you want,
result = [sku for sku in df['sku'] if not sku.isdigit()]
This should work:
result = []
for i in range(len(ass)):
try:
int(df['sku'][i])
except ValueError:
result.append(df['sku'][i])
Related
I have the following code:
def right_rounding(min_vol):
try:
splitted = str(min_vol).split('.')
if float(splitted[0]) >= 1:
return 0
else:
return len(splitted[1])
except Exception as e:
print("Error code =",mt5.last_error())
print(e, 'error ', traceback.format_exc())
pass
It works right most of the time but sometimes it gives index out of range
index out of range
It's because splitted, which is of type str, is of length 1.
You can try printing the list splitted and you'll see that you have a list with just 1 element in it, and that would be min_vol.
When you split a string with some delimiter (in this case it is .), the returned value will be the string itself if the delimiter doesn't exist.
I am not sure what you're trying to achieve with that code, but the issue is that there is no splitting[1] because the list doesn't have an element in the 1st index.
If you want to access the last element of the list, you can enter -1 as the index and it will work.
I have a string that I'd like to format but the values I'm using to format may or may not be proper values (None, or ''). In any event that one of these improper values is passed, I still want the string to format, but ignoring any values that will not work. For example:
mystring = "{:02d}:{:02d}"
mystring.format('', 1)
In this case I'd like my output to be :01, thus negating the fact that '' won't work for the first value in the string. I looked at something like
class Default(dict):
def __missing__(self, key):
return key.join("{}")
d = Default({"foo": "name"})
print("My {foo} is {bar}".format_map(d)) # "My name is {bar}"
But as I'm not using a dictionary for values, I don't think this solution will work for me.
You could write your own formatter and override format_field() to catch these errors and just returns empty strings. Here's the basics (you might want to edit to only catch certain errors):
import string
class myFormat(string.Formatter):
def format_field(self, value, format_spec):
try:
return super().format_field(value, format_spec)
except ValueError:
return ''
fmt = myFormat()
mystring = "{:02d}:{:02d}"
print(fmt.format(mystring, *(2, 1)))
# 02:01
print(fmt.format(mystring, *('', 1)))
# :01
You could use a try-except to check if each value is valid:
out = []
for v in ['', 1]:
# Check if v can be converted to a decimal number
try:
out.append(format(v, '02d'))
except (ValueError, TypeError):
out.append('')
print(':'.join(out)) # -> :01
This piece of code will ask for input, compare input with content of lists and, if input and content match, return input.
If input is not in list user will be asked again for input.
def get_input(tested_list):
corect_input = False
while not corect_input:
try:
# we are comparing input to list of lists content
my_input = str.lower((input("Enter here: ")))
for line in a_list:
if my_input == line[2].lower():
return my_input
except ValueError:
print("????")
else:
corect_input = False
Now questions (I'm very beginner. Try-Except-Else is all very new for me) :
Is there any reason here to include 'except' line? Since input is converted to string, I can't see way to input anything what will cause any error.
What kind of error shall I use after 'except'.
How shall I write this piece of code to be better / cleaner/ more pythonic? :) .
thank you
First issue to note is that a_list in your function should be replaced by tested_list. a_list has not been defined and will cause an error.
There are at least 2 possible errors you can face:
AttributeError, if the 2nd index of a sublist in tested_list is not a string, e.g. if it is an integer.
IndexError, if the 2nd index of a sublist in tested_list does not exist, e.g. if the sublist is of length 2.
However, to make your try / except clause useful in this context, you need to define it within the for loop. Below is an example.
def get_input(tested_list):
correct_input = False
while not correct_input:
my_input = str.lower((input("Enter here: ")))
for line in tested_list:
try:
if my_input == line[2].lower():
return my_input
except (AttributeError, IndexError):
print("An error has occurred")
else:
correct_input = False
Forgive me, I'm new to Python.
Given a string that starts with a float of indeterminate length and ends with the same, how can I extract both of them into an array, or if there is just one float, just the one.
Example:
"38.00,SALE ,15.20"
"69.99"
I'd like to return:
[38.00, 15.20]
[69.99]
You could also use regex to do this
import re
s = "38.00,SALE ,15.20"
p = re.compile(r'\d+\.\d+') # Compile a pattern to capture float values
floats = [float(i) for i in p.findall(s)] # Convert strings to float
print floats
Output:
[38.0, 15.2]
def extract_nums(text):
for item in text.split(','):
try:
yield float(item)
except ValueError:
pass
print list(extract_nums("38.00,SALE ,15.20"))
print list(extract_nums("69.99"))
[38.0, 15.2]
[69.99]
However by using float conversion you are losing precision, If you want to keep the precision you can use decimal:
import decimal
def extract_nums(text):
for item in text.split(','):
try:
yield decimal.Decimal(item)
except decimal.InvalidOperation:
pass
print list(extract_nums("38.00,SALE ,15.20"))
print list(extract_nums("69.99"))
[Decimal('38.00'), Decimal('15.20')]
[Decimal('69.99')]
You said you're only interested in floats at the start and end of the string, so assuming it's comma-delimited:
items = the_string.split(',')
try:
first = float(items[0])
except (ValueError, IndexError):
pass
try:
second = float(items[-1])
except (ValueError, IndexError):
pass
We have to wrap the operations in exception handlers since the value might not be a valid float (ValueError) or the index might not exist in the list (an IndexError).
This will handle all cases including if one or both of the floats is omitted.
You can try something like
the_string = "38.00,SALE ,15.20"
floats = []
for possible_float in the_string.split(','):
try:
floats.append (float (possible_float.strip())
except:
pass
print floats
Try a list comprehension:
just_floats = [i for i in your_list.split(',') if i.count('.') == 1]
first you split the string where the commas are, then you filter through the string and get rid of values that don't have a decimal place
import re
map(float, filter(lambda x: re.match("\s*\d+.?\d+\s*", x) , input.split(","))
Input : input = '38.00,SALE ,15.20' Output: [38.0, 15.2]
Input : input = '38.00,SALE ,15.20, 15, 34.' Output: [38.0, 15.2, 15.0, 34.0]
Explanation:
Idea is to split the string : list_to_filter = input.split(",") splits on ,
Then using regex filter strings which are real numbers: filtered_list = filter(<lambda>, list_to_filter) , here item is included in output of filter if lamda expression is true. So when re.match("\s*\d+.?\d+\s*", x) matches for string x filter keeps it.
And finally convert into float. map(float, filtered_list). What it does is apply float() function to each element of the list
Split the input, check if each element is numeric when the period is removed, convert to float if it is.
def to_float(input):
return [float(x) for x in input.split(",") if unicode(x).replace(".", "").isdecimal()]
I'm trying to debug some Python 2.7.3 code to loop through a list of items and convert each to a string:
req_appliances = ['9087000CD', 'Olympus', 185]
for i in range(0, len(req_appliances)):
req_appliances[i] = str(req_appliances[i])
print req_appliances
The output is as follows:
['9087000CD', 'Olympus', '185']
In the example above, I've set the value of req_appliances explicitly to test the loop. In the actual code, req_appliances is an argument to a function. I do not know the type of the argument at runtime, but it appears to be a list of scalar values. I do know that when I invoke the function, I see the following error message:
File ".../database.py", line 8277, in get_report_appliance_list
req_appliances[i] = str(req_appliances[i])
TypeError: 'str' object does not support item assignment
I'm trying to deduce for what values of argument req_appliances it would be possible for this error condition to arise. It seems to me that all of the values are scalar and each (even if immutable) should be a valid LHS expressions in an assignment. Is there something I'm missing here? Here is the code in context, in the function in which it is defined:
def get_report_appliance_list(self, req_appliances, filter_type=None):
appliances = {}
appliance_list = []
if filter_type != None:
if filter_type not in ('appliances', 'servers'):
raise ValueError("appliance filter_type must be one of 'appliances' or 'servers'")
active_con = self.get_con()
if active_con is None:
raise Exception('No database connections are available.')
con = None
in_expr_items = ''
if req_appliances != None:
# Create a string like '(%s, %s, ...)' to represent
# the 'in' expression items in the SQL.
print(req_appliances)
for i in range(0, len(req_appliances)):
req_appliances[i] = str(req_appliances[i])
in_expr_items += '%s,'
in_expr_items = '(' + in_expr_items[:-1] + ') '
An str acts like a sequence type (you can iterate over it), but strings in Python are immutable, so you can't assign new values to any of the indices.
I expect what's happening here is that you're trying to run this when req_appliances is a str object.
I came up with two ways to fix this:
First, just check if it's a str before you iterate over it:
if isinstance(req_appliances, basestring):
return req_appliances
Second, you could check each item to see if it's already a string before trying to assign to it.
req_appliances = ['9087000CD', 'Olympus', 185]
for i in range(0, len(req_appliances)):
if req_appliances[i] != str(req_appliances[i]):
req_appliances[i] = str(req_appliances[i])
print req_appliances
Here, I'm actually checking whether the member is equal to its string representation. This is true when you iterate over strings.
>>> a = 'a'
>>> a[0] == str(a[0])
True
This is not really an answer to your question, but a style advise. If you happen to use for i in range(0, len(something)) a lot you should either use for i, obj in enumerate(something), map(func, something) or a list comprehension [func(x) for x in something].
Another red flag is the use of string += inside a loop. Better create an array and join it. This also eliminates the need to do stuff like [-1] in order to get rid of trailing commas.
Regarding your code you could simplify it a lot:
def get_report_appliance_list(self, req_appliances, filter_type=None):
appliances = {}
appliance_list = []
if filter_type not in (None, 'appliances', 'servers'):
raise ValueError("appliance filter_type must be one of 'appliances' or 'servers'")
active_con = self.get_con()
if active_con is None:
raise Exception('No database connections are available.')
# Create a string like '(%s, %s, ...)' to represent
# the 'in' expression items in the SQL.
in_expr_items = ','.join(['%s'] * len(req_appliances)
req_appliances = map(str, req_appliances)
...
Apart from that I would recommend that get_con() throws so you do not have to check for None in your code.