Re: [Tutor] Python 3: string to decimal conversion
On Sat, May 21, 2016 at 01:34:20PM -0500, Saidov wrote: > "decimal.InvalidOperation was unhandled by user code > Message: []" > > *Question: *I tried looking up the meaning of this error, but couldn't find > anything on the internet. *Can someone help me understand what's wrong with > my code?* https://duckduckgo.com/html/?q=decimal+InvalidOperation+python will take you to the docs for Python 2. Changing the URL to version 3 gives us: https://docs.python.org/3/library/decimal.html and searching for InvalidOperation gives us: https://docs.python.org/3/library/decimal.html#decimal.InvalidOperation which is not a lot of help as it only lists *some* of the things which will lead to that error, but we can try it at the interactive interpreter: py> import decimal py> decimal.Decimal("25") Decimal('25') py> decimal.Decimal("25x") Traceback (most recent call last): File "", line 1, in decimal.InvalidOperation: [] So the problem here is that when you call Decimal() with an invalid argument, you are expecting a ValueError, but Python raises decimal.InvalidOperation instead: > try: > expenses[ts.Date(row[0]).month] += decimal.Decimal(row[4]) > except ValueError: > pass -- Steve ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Python 3: string to decimal conversion
Thank you all for the useful feedback. I am new to programming so bear with me while I learn the rules... I have run Cameron's code to print the values and have the traceback results. please see below. -Original Message- From: c...@zip.com.au [mailto:c...@zip.com.au] Sent: Saturday, May 21, 2016 10:32 PM To: Saidov Cc: tutor@python.org Subject: Re: [Tutor] Python 3: string to decimal conversion Hi Saidov, I'm going to reply to your post inline, as that is the etiquette here and in many technical mailing lists. On 21May2016 13:34, Saidov wrote: >I am working on a piece of python code that's supposed to help me >manage a >budget: >1. Read a banking statement >2. Categorize expenses and income by month and by type 3. Print out a >report comparing the projected expenses/income with actual numbers. Thank you for providing your problem's context. >*File characteristics:* >Banking statement in a csv file format. >contents: 5 columns, 1st column= date, 4 column=expenses date format: >mm/dd/, type: string expenses format: ($0.00), type: string income >format: $0.00, type: string > >*Python Version: 3.5 (64 bit)* >IDE:Microsoft Visual Studio Community 2015 Version 14.0.25123.00 Update >2 > >Python Tools for Visual Studio 2.2.40315.00 >Python Tools for Visual Studio provides IntelliSense, projects, >templates, Interactive windows, and other support for Python developers. And this level of detail is very welcome. >*Problem:* > I want to convert expense/income values into a decimal form so I could >sum them into appropriate buckets according to the month in which they >occur. I am getting the following error message when I run my code: > >"decimal.InvalidOperation was unhandled by user code >Message: []" Please always provide the full traceback which accompanied the exception report; there should be a list of code lines indicating the call stack where the error occurred. This provides valuable context for figuring out where in your code to look for issues. Absent that context, I will have a guess at where this might be occurring: [...] >files =['export.csv'] >with open("budgetfile.csv","wt") as fw: >writer = csv.writer(fw) >for file in files: >with open(file) as csvfile: >records = csv.reader(csvfile, quoting=csv.QUOTE_NONE) [...] >for row in records: [...] >try: >expenses[ts.Date(row[0]).month] += decimal.Decimal(row[4]) >except ValueError: >pass I would guess that this: decimal.Decimal(row[4]) is the source of your error; it seems to be the only place where you actually convert a string into a Decimal. I would guess that when handed a bad string this raises decimal.ConversionSyntax instead of a ValueError. I suggest that you print out the value of row[4] before the "try" statement: print("row[4] =", repr(row[4])) Note the use of repr: it gets you better detail about the value of the string. Thank you for a well presented question. Finally, please try to post in plain text instead of rich text; this is a plain text list and if you post in rich text or HTML (a) some hinting you have have povided like coloured text will not be presented to readers and (b) some things, particularly code, and be presented visually mangled, which makes things hard to read and debug. - + decimal module + expenses {1: Decimal('0'), 2: Decimal('0'), 3: Decimal('0'), 4: Decimal('0'), 5: Decimal('0'), 6: Decimal('0'), 7: Decimal('0'), 8: Decimal('0'), 9: Decimal('0'), 10: Decimal('0'), 11: Decimal('0'), 12: Decimal('0')} dict row[0] '"1/1/2016"' str row[4] '""' str + ts module ipython traceback: row[4]= ' "" ' Traceback (most recent call last): File "C:\mypath\visual studio 2015\Projects\Budget\Budget\Budget.py", line 28, in expenses[ts.Date(row[0]).month] += decimal.Decimal(row[4]) decimal.InvalidOperation: [] I think the problem may be caused by an empty string value that is passed to decimal.Decimal function. The csv file contains some empty cells and I wanted the code to ignore them. That's why I had the ValueError exception. -- Cheers, Cameron Simpson ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Python 3: string to decimal conversion
On 22/05/16 14:19, US wrote: >>with open(file) as csvfile: >>records = csv.reader(csvfile, quoting=csv.QUOTE_NONE) > [...] >>for row in records: > [...] >>try: >>expenses[ts.Date(row[0]).month] += > decimal.Decimal(row[4]) >>except ValueError: >>pass > I think the problem may be caused by an empty string value that is > passed to decimal.Decimal function. The csv file contains some empty > cells and I wanted the code to ignore them. That's why I had the > ValueError exception. If you know you are going to get some invalid data in your loop you should test for it before the operation and use 'continue' to force the loop to start the next iteration. You could still catch the invalid operation error, just in case... Although, if you don't expect it and don't know how to handle it then it's probably better to let Python just do its thing and give you the traceback. Like this: with open(file) as csvfile: records = csv.reader(csvfile, quoting=csv.QUOTE_NONE) #... for row in records: if not row[4]: continue# coz its empty else: expenses[ts.Date(row[0]).month] += decimal.Decimal(row[4]) HTH -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Python 3: string to decimal conversion
On 22May2016 08:19, Saidov wrote: Thank you all for the useful feedback. I am new to programming so bear with me while I learn the rules... I have run Cameron's code to print the values and have the traceback results. please see below. [...] for row in records: [...] try: expenses[ts.Date(row[0]).month] += decimal.Decimal(row[4]) except ValueError: pass [...] I suggest that you print out the value of row[4] before the "try" statement: print("row[4] =", repr(row[4])) [...] + decimal module + expenses {1: Decimal('0'), 2: Decimal('0'), 3: Decimal('0'), 4: Decimal('0'), 5: Decimal('0'), 6: Decimal('0'), 7: Decimal('0'), 8: Decimal('0'), 9: Decimal('0'), 10: Decimal('0'), 11: Decimal('0'), 12: Decimal('0')} dict row[0] '"1/1/2016"' str row[4] '""' str + ts module ipython traceback: row[4]= ' "" ' Traceback (most recent call last): File "C:\mypath\visual studio 2015\Projects\Budget\Budget\Budget.py", line 28, in expenses[ts.Date(row[0]).month] += decimal.Decimal(row[4]) decimal.InvalidOperation: [] I think the problem may be caused by an empty string value that is passed to decimal.Decimal function. The csv file contains some empty cells and I wanted the code to ignore them. That's why I had the ValueError exception. I have two observations here: Your strings in row[4] are not empty. If that output is repr(row[4]) then row[4] contains the text: "" That is a two character string consisting of two quote characters. Normally the csv.reader module will handle that for you, but I see that you passed the paramater: quoting=csv.QUOTE_NONE to it when setting it up. It looks to me like your CSV file is a conventional one with quotes around string values. By passing csv.QUOTE_NONE you prevent the csv module from handling those for you and you get the "raw" column values. So a column with an empty string is probably written as "" in the file. Could you show is the first line or so from your CSV file? That should tell us and you whether the file is "bare" comma separate values or the far more common quoted format. If it is the quoted format, just remove the "quoting=csv.QUOTE_NONE" parameter altogether - the default for the csv module is quoted and it is _usually_ what is wanted. Of course you need to know one way or the other, so examine the CSV file itself. The other observation is that you're trying to catch ValueError, when plainly the Decimal module is raising decimal.InvalidOperation. So you should catch that instead. HOWEVER, just catching it and ignoring that row will _silently_ discard good input if you program is incorrect. You should almost always emit an error message or perform some other very specific action when you catch an exception. Alan has suggested that you test specificly for an empty string. I agree: you should act on exactly what is expected. By blindly catching ValueError or decimal.InvalidOperation and not reporting the string that caused it to happen you will silently ignore all kinds of unexpected input. So I would advocate some code like this, similar to Alan's: if not row[4]: # empty column - we expect this and ignore it pass else: try: expenses[ts.Date(row[0]).month] += decimal.Decimal(row[4]) except decimal.InvalidOperation as e: print("unexpected expenses value: %r" % (row[4],)) which will report the offending values, and presumably you expect either an empty column or a _valid_ expense value. Cheers, Cameron Simpson ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor