Re: [Tutor] Python 3: string to decimal conversion

2016-05-24 Thread Peter Otten
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

2016-05-23 Thread cs

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

2016-05-23 Thread US
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

2016-05-23 Thread Peter Otten
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

2016-05-23 Thread Alan Gauld via Tutor
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

2016-05-23 Thread US
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

2016-05-22 Thread cs

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

2016-05-22 Thread Alan Gauld via Tutor
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

2016-05-22 Thread US
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

2016-05-22 Thread Steven D'Aprano
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

2016-05-21 Thread cs

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

2016-05-21 Thread Ben Finney
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