error handling in user input: is this natural or just laborious

James Stroud jstroud at mbi.ucla.edu
Fri Oct 6 18:00:53 EDT 2006


James Stroud wrote:
> sam wrote:
> 
>> hi all,
>>
>> i'm starting to put together a program to simulate the performance of
>> an investment portfolio in a monte carlo manner doing x thousand
>> iterations and extracting data from the results.
>>
>> i'm still in the early stages, and am trying to code something simple
>> and interactive to get the percentages of the portfolio in the five
>> different investment categories. i thought i'd get in with the error
>> handling early so if someone types in something wrong (like a word), or
>> the numbers don't add up to 100%, the error would be caught immediately
>> and the user sent back to the start of the loop. granting that there
>> may be better ways of doing this, if i decide that i do want to do it
>> like this (i.e. a single error requires all data to be re-entered, not
>> unreasonable for only five items), is this a good way of doing it or a
>> confusing way of doing it from the perspective of readability and
>> maintenance:
>>
>> while True:
>>
>>     cash, bond, blue, tech, dev = 0,0,0,0,0
>>     check=False
>>
>>     try:
>>         cash=input('Please enter a cash percentage for the portfolio: ')
>>     except NameError:
>>         print 'That is not a number. Please start again and remember 
>> to enter
>> integers.'
>>     else:
>>         try:
>>             bond=input('Please enter a bond portfolio for the 
>> portfolio: ')
>>
>>         except NameError:
>>             print 'That is not a number. Please start again and 
>> remember to
>> enter integers.'
>>         else:
>>             try:
>>                 blue=input('Please enter a blue-chip percentage for 
>> the portfolio:
>> ')
>>             except NameError:
>>                 print 'That is not a number. Please start again and 
>> remember to
>> enter integers.'
>>             else:
>>                 try:
>>                     tech=input('Please enter a tech stocks percentage 
>> for the
>> portfolio: ')
>>                 except NameError:
>>                     print 'That is not a number. Please start again 
>> and remember to
>> enter integers.'
>>                 else:
>>                     try:
>>                         dev=input('Please enter a developing countries 
>> index for the
>> portfolio: ')
>>                         check=True
>>                     except NameError:
>>                         print 'That is not a number. Please start 
>> again and remember to
>> enter integers.'
>>
>>     if cash+bond+blue+tech+dev==100:
>>         break
>>     if cash+bond+blue+tech+dev!=100 and check!= False:
>>         print 'Those numbers do not sum to 100. Please start again.'
>>
>>
>>
>> i know it's a bit verbose, but it was the nested try clauses i was
>> really wondering about. is the code immediate legible to experienced
>> python users? or does it look like gibberish at first?
>>
>> just hoped for some fresh eyes on it.
>>
>> thanks,
>>
>> sam
>>
>> PS making check=True just saves the code from printing 'those numbers
>> don't sum to 100' if they haven't all been entered, which looks kind of
>> silly.
>>
> 
> It looks pretty rough. I think tabs are a very bad idea. Patently. Tabs 
> should be reserved for tables, for which tabs were named. If they were 
> meant to be used for indenting, they would have been named "indenters".
> 
> Try blocks in my opinion are a good idea but they need to be done 
> correctly. You should also consider thinking more in terms of procedural 
> programming than linear.
> 
> Also, the best way would be by gui. See this book for the best resource 
> (IMHO) for python gui programming:
> 
>          http://www.manning.com/grayson/
> 
> I think the following is much better technique and is more fun than 
> laborious to code:
> 
> 
> def get_pcts(prompts):
>   prompts = ['gross product', 'repleat divisional', 'sales quota']
>   pcts = [get_pct(prompt) for prompt in prompts]
>   sum_pcts = sum(pcts)
>   if (sum_pcts > 100.0001) or (sum_pcts < 99.999):
>     raise ValueError, "Values didn't add to 100."
>   return pcts
> 
> def get_pct(pct_type):
>   pct = raw_input('Input percent of %s:' % pct_type)
>   return float(pct)
> 
> def get_values():
>   prompts = ['gross product', 'net outsource', 'sales quota']
>   while True:
>     try:
>       pcts = get_pcts(prompts)
>       return dict(zip(prompts, pcts))
>     except ValueError, e:
>       print e
>       print 'Try again dude.'
> 
> """
> Here's a test
>  >>> print get_values()
> Input percent of gross product:21
> Input percent of repleat divisional:22
> Input percent of sales quota:57
> {'sales quota': 57.0, 'gross product': 21.0, 'net outsource': 22.0}
> """
> 
> James
> 

Oops, I forgot to remove a line in the final code:

def get_pcts(prompts):
   pcts = [get_pct(prompt) for prompt in prompts]
   sum_pcts = sum(pcts)
   if (sum_pcts > 100.0001) or (sum_pcts < 99.999):
     raise ValueError, "Values didn't add to 100."
   return pcts

def get_pct(pct_type):
   pct = raw_input('Input percent of %s:' % pct_type)
   return float(pct)

def get_values():
   prompts = ['gross product', 'net outsource', 'sales quota']
   while True:
     try:
       pcts = get_pcts(prompts)
       return dict(zip(prompts, pcts))
     except ValueError, e:
       print e
       print 'Try again dude.'


"""
Testing:

 >>> print get_values()
Input percent of gross product:22
Input percent of net outsource:21
Input percent of sales quota:57
{'sales quota': 57.0, 'gross product': 22.0, 'net outsource': 21.0}
 >>> print get_values()
Input percent of gross product:15.1
Input percent of net outsource:88.2
Input percent of sales quota:19.8
Values didn't add to 100.
Try again dude.
Input percent of gross product:bob
invalid literal for float(): bob
Try again dude.
"""

-- 
James Stroud
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095

http://www.jamesstroud.com/



More information about the Python-list mailing list