Re: [Tutor] Python 3: string to decimal conversion
c...@zip.com.au wrote: > On 23May2016 12:18, Saidov wrote: >>Thanks everyone for all your help. This solved my problem with >>parenthesis and $ signs in the data: >> >>if not row[4]: >>pass >>else: >>try: >>expenses[ts.Date(row[0]).month] += >>decimal.Decimal(row[4].strip('()$ ,').replace(',','')) >>except decimal.InvalidOperation as e: >>print("unexpected expenses value: %r" % (row[4])) > > These are three things to remark on with your new code: Noughtily? Whatever you do, the conversion is complex enough to put it into a separate function. This makes it easier to test the code against typical input and corner cases. > Firstly, it is best to put try/except around as narrow a piece of code as [...] ___ 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 23May2016 12:18, Saidov wrote: Thanks everyone for all your help. This solved my problem with parenthesis and $ signs in the data: if not row[4]: pass else: try: expenses[ts.Date(row[0]).month] += decimal.Decimal(row[4].strip('()$ ,').replace(',','')) except decimal.InvalidOperation as e: print("unexpected expenses value: %r" % (row[4])) These are three things to remark on with your new code: Firstly, it is best to put try/except around as narrow a piece of code as possible. In your code about, you would catch decimal.InvalidOperation from any of the operations, including the strip and .replace operations. While it happens that these do not raise that exception, the problem is that when an exception is raised you have a much vaguer idea of where it came from, especially with more common exceptions like ValueError. Therefore I would suggest reshaping the above like this: numeric_expense = row[4].strip('()$ ,').replace(',', '') try: expense = decimal.Decimal(numeric_expense) except decimal.InvalidOperation as e: print("unexpected numeric expsense: %r (%s)" % (numeric_expense, e)) else: expenses[ts.Date(row[0]).month] += expense In this way you are watching for _only_ the decimal.Decimal() call, not the other methods. Also, it makes it easy to report the actual string that caused the trouble (numeric_expense) because you have now pulled it out and given it a nice name. This means that your note reporting an error about row[4] _before_ it got cleaned up, you're reporting about how it was after the cleanup. Also, we're printing the exception itself in the message as well as the string: here it may not help more, but with many exceptions there will be further detail which can be helpful, so it is good practice to print the exception (e). Second, error messages should go to the program's error output, which is a separate output stream from stdout. So the print should look like this: print(., file=sys.stderr) When it is all going to your terminal you won't see the f=difference, but as soon as your program is run like this: python my-program.py >report.txt you will get the "report" information in your file and the error output will still show up on your terminal where you will see it. Thirdly, your .strip('()') is throwing away the brackets around the expense. As Alan pointed out, it is common convention in accounting to express negaitve values (losses, withdrawals, etc) in brakcets. So this "4.00" means 4.00 and this "(4.00)" means -4.00. And in consequence you should probably be _subtracting_ any value in brackets instead of adding it. This is why ALan had a distinct if-statement to recognise the brackets. Example, untested: if row[4].startswith('(') and row[4].endswith(')'): row[4] = row[4][1:-1] negative = True else: negative = False # ... string $ sign and commas, convert to Decimal ... try: except : else: if negative: expense = -expense expenses[ts.Date(row[0]).month] += expense As your code current is, it is adding all the negative values, which may not be what is needed. 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
Thanks everyone for all your help. This solved my problem with parenthesis and $ signs in the data: if not row[4]: pass else: try: expenses[ts.Date(row[0]).month] += decimal.Decimal(row[4].strip('()$ ,').replace(',','')) except decimal.InvalidOperation as e: print("unexpected expenses value: %r" % (row[4])) On Mon, May 23, 2016 at 5:06 AM, Peter Otten <__pete...@web.de> wrote: > US wrote: > >> Thank you both for suggesting a way to handle errors. I have run the >> suggested code. What I learned is that all the values (not only empty >> cells) seem to be invalid for decimal.Decimal function. >> >> I tried the float() function instead of decimal.Decimal and got an >> error message: could not convert string to float: '($75.59)'. >> >> I also checked the type of values in row[4]. All the values passed on >> to decimal.Decimal () function are indeed of string type... >> >> Is there anything I can do to the formatting of the csv file to make >> it 'readable' for decimal.Decimal function? >> >> Here is my updated code along with the output I got from running it: >> >> >> code: >> import numpy as np >> import csv >> import timestring as ts >> import decimal >> >> months= [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] >> expenses = {x: decimal.Decimal() for x in months} >> income = {x: decimal.Decimal() for x in months} >> test = [] >> >> exp_cat = [] >> income_cat = [] >> >> files =['export.csv'] >> >> with open("budgetfile.csv","wt") as fw: >> writer = csv.writer(fw) >> for file in files: >> with open(file, newline ='' ) as csvfile: >> records = csv.reader(csvfile) >> print("Processing file {}. \n" .format(file)) >> header = next(records) >> for row in records: >> print("row[4] =", repr(row[4]), "value type =", >> type(row[4])) >> >> if not row[4]: >> 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],)) > >> last 4 lines of output: >> [4] = '($10.00)' value type = >> unexpected expenses value: '($10.00)' >> row[4] = '($287.42)' value type = >> unexpected expenses value: '($287.42)' > > Perhaps you should use a custom conversion routine like to_decimal() below: > > class MissingValue(ValueError): > pass > > > @contextlib.contextmanager > def expect(exc): > """Ensure that an excption of type `exc` was raised. > > Helper for the doctests. > """ > try: > yield > except exc: > pass > except: > raise AssertionError( > "Wrong exception type (expected {})".format(exc)) > else: > raise AssertionError("Exception was not raised") > > > def to_decimal(s): > """ > >>> with expect(MissingValue): > ... to_decimal(" ") > >>> with expect(ValueError): > ... to_decimal("42") > >>> to_decimal("$12.34") > Decimal('12.34') > >>> to_decimal("($34.56)") > Decimal('-34.56') > >>> with expect(ValueError): > ... to_decimal("foo") > >>> with expect(ValueError): > ... to_decimal("$bar") > >>> with expect(ValueError): > ... to_decimal("($baz)") > """ > s = s.strip() # remove leading/trailing whitespace > if not s: > raise MissingValue("Empty amount") > if s.startswith("(") and s.endswith(")"): > sign = -1 > s = s[1:-1] # remove parens > else: > sign = 1 > if not s.startswith("$"): > raise ValueError("No leading $ found") > s = s[1:] # remove $ > try: > value = decimal.Decimal(s) > except decimal.InvalidOperation as err: > raise ValueError(err.args[0]) from None > return sign * value > > > That way you can spell out explicitly what the allowed values may look like, > and if (e. g.) you want to allow for grouping you can easily add another > preprocessing step to remove the commas. Use it like so in your code: > > ... > for row in records: > try: > amount = to_decimal(row[4]) > except ValueError as err: > print(err, file=sys.stderr) > else: > ... # add amount to expenses > ... > > ___ > Tutor maillist - Tutor@python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor ___ 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
US wrote: > Thank you both for suggesting a way to handle errors. I have run the > suggested code. What I learned is that all the values (not only empty > cells) seem to be invalid for decimal.Decimal function. > > I tried the float() function instead of decimal.Decimal and got an > error message: could not convert string to float: '($75.59)'. > > I also checked the type of values in row[4]. All the values passed on > to decimal.Decimal () function are indeed of string type... > > Is there anything I can do to the formatting of the csv file to make > it 'readable' for decimal.Decimal function? > > Here is my updated code along with the output I got from running it: > > > code: > import numpy as np > import csv > import timestring as ts > import decimal > > months= [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] > expenses = {x: decimal.Decimal() for x in months} > income = {x: decimal.Decimal() for x in months} > test = [] > > exp_cat = [] > income_cat = [] > > files =['export.csv'] > > with open("budgetfile.csv","wt") as fw: > writer = csv.writer(fw) > for file in files: > with open(file, newline ='' ) as csvfile: > records = csv.reader(csvfile) > print("Processing file {}. \n" .format(file)) > header = next(records) > for row in records: > print("row[4] =", repr(row[4]), "value type =", > type(row[4])) > > if not row[4]: > 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],)) > last 4 lines of output: > [4] = '($10.00)' value type = > unexpected expenses value: '($10.00)' > row[4] = '($287.42)' value type = > unexpected expenses value: '($287.42)' Perhaps you should use a custom conversion routine like to_decimal() below: class MissingValue(ValueError): pass @contextlib.contextmanager def expect(exc): """Ensure that an excption of type `exc` was raised. Helper for the doctests. """ try: yield except exc: pass except: raise AssertionError( "Wrong exception type (expected {})".format(exc)) else: raise AssertionError("Exception was not raised") def to_decimal(s): """ >>> with expect(MissingValue): ... to_decimal(" ") >>> with expect(ValueError): ... to_decimal("42") >>> to_decimal("$12.34") Decimal('12.34') >>> to_decimal("($34.56)") Decimal('-34.56') >>> with expect(ValueError): ... to_decimal("foo") >>> with expect(ValueError): ... to_decimal("$bar") >>> with expect(ValueError): ... to_decimal("($baz)") """ s = s.strip() # remove leading/trailing whitespace if not s: raise MissingValue("Empty amount") if s.startswith("(") and s.endswith(")"): sign = -1 s = s[1:-1] # remove parens else: sign = 1 if not s.startswith("$"): raise ValueError("No leading $ found") s = s[1:] # remove $ try: value = decimal.Decimal(s) except decimal.InvalidOperation as err: raise ValueError(err.args[0]) from None return sign * value That way you can spell out explicitly what the allowed values may look like, and if (e. g.) you want to allow for grouping you can easily add another preprocessing step to remove the commas. Use it like so in your code: ... for row in records: try: amount = to_decimal(row[4]) except ValueError as err: print(err, file=sys.stderr) else: ... # add amount to expenses ... ___ 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 23/05/16 02:45, US wrote: > I tried the float() function instead of decimal.Decimal and got an > error message: could not convert string to float: '($75.59)'. The problem is that the functions don;t recognize the parens as a negative sign. You will need to convert them yourself. I suggest you write a function that takes a string and if it starts with parens then strip them off and prepend a negative sign, otherwise return the original. You will also need to get rid of the $ sign... Something like: def normalizeValue(val): if amt.startswith('(') and amt.endswith(')'): amt = '-' + amt[1:-1] return amt.replace('$','') Then call that when you try to convert to Decimal -- 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 Sun, May 22, 2016 at 5:36 PM, wrote: > 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 > 'C:\mypath\Anaconda3\\lib\\site-packages\\timestring\\__init__.py'> >> 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. > Thanks, the csv.QUOTE_NONE was one of the parameters i changed earlier. It didn't make any difference, unfortunately. I kept getting the same error. I visually inspected the csv file and the empty cells show up empty. negative numbers are recorded as ($0.00), non-negative numbers as: $0.00 Here are the first four lines: Date No. Description Type Debit Credit 1/1/2016 income ex-2387280 CREDIT $303.65 1/3/2016 income ex-4732847 CREDIT $3.00 1/4/2016 insurance DEBIT ($75.59) > 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 Thank you both for suggesting a way to handle errors. I have run the suggested code. What I learned is that all the values (not only empty cells) seem to be invalid for decimal.Decimal function. I tried the float() function instead of decimal.Decimal and got an error message: could not convert string to float: '($75.59)'. I also checked the type of values in row[4]. All the values passed on to decimal.Decimal () function are indeed of string type... Is there anything I can do to the formatting of the csv file to make it 'readable' for decimal.Decimal function? Here is my updated code along wit
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
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
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 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
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. 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
Saidov writes: > *Python Version: 3.5 (64 bit)* > IDE:Microsoft Visual Studio Community 2015 Your IDE is apparently suppressing, or hiding somewhere, the full traceback of the exception. It's important that you always have that in front of you when trying to diagnose an un-handled exception. > "decimal.InvalidOperation was unhandled by user code > Message: []" So, this tells us only the name of the exception, not the location in the code, nor the call stack that produced it. You need to find and paste the full traceback text. > *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?* Please turn off any “rich” or HTML formatting of your message, post in plain text only. You need the text of your message to survive without any mangling. -- \ “Give a man a fish, and you'll feed him for a day; give him a | `\religion, and he'll starve to death while praying for a fish.” | _o__) —Anonymous | Ben Finney ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] Python 3: string to decimal conversion
Hello all, 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. *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. *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: []" *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?* Below is my code: ++ import numpy as np import csv import timestring as ts import decimal months= [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] expenses = {x: decimal.Decimal() for x in months} income = {x: decimal.Decimal() for x in months} exp_cat = [] income_cat = [] 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) print("Processing file {}. \n" .format(file)) header = next(records) for row in records: row[4].replace("($","") row[4].replace(")","") row[4].replace('"', '') try: expenses[ts.Date(row[0]).month] += decimal.Decimal(row[4]) except ValueError: pass + ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor