[Python-ideas] "try with" syntactic sugar

Bruce Frederiksen dangyogi at gmail.com
Thu Feb 26 19:29:23 CET 2009


Daniel Stutzbach wrote:
> Here's an updated regular expression that does a better job of 
> ignoring comments and strings:
>
> re_with = re.compile(r'(try:[ \t]*)?[\r\n]+[ \t]+with .*:')
Here's an even better version:

#!/usr/bin/python
import re, sys

re_with = re.compile(r'''
  ^(?P<indent>\s*)                             # capture the indent
   try:
   (?:[ \t]*(?:\#.*)?[\r\n]+)?                 # newlines (ignoring 
comments)
   (?P<with>
      (?P=indent)[ \t]+                        # at higher indent level
      with\s (?:[^#:]*(?:(?:\#.*)?[\r\n]+)?)*: # with .*: (ignoring comments
                                               # and newlines before :)
   )?                                          # end (?P<with>)
''', re.MULTILINE | re.VERBOSE)               

try_with = 0
total = 0
for fname in sys.argv[1:]:
    data = open(fname).read()
    for match in re_with.finditer(data):
        if match.group('with'): try_with += 1
        total += 1
       
print 'try-with:', try_with, 'out of:', total, '(', 
try_with*100.0/total,'%)'

When I run this on a project of mine, I get:

try-with: 1 out of: 87 ( 1.14942528736 %)

The pattern that I find myself using is with/for, which can be counted 
by this program:

#!/usr/bin/python
import re, sys

re_with = re.compile(r'''
  ^(?P<indent>\s*)                            # capture the indent
   with\s (?:[^#:]*(?:(?:\#.*)?[\r\n]+)?)*:   # with .*: (ignoring comments
                                              # and newlines before :)
   (?:[ \t]*(?:\#.*)?[\r\n]+)?                # newlines (ignoring comments)
   (?P<for>
      (?P=indent)[ \t]+                       # at higher indent level
      for\s (?:[^#:]*(?:(?:\#.*)?[\r\n]+)?)*: # for .*: (ignoring comments
                                              # and newlines before :)
   )?                                         # end (?P<for>)
''', re.MULTILINE | re.VERBOSE)

with_for = 0
total = 0
for fname in sys.argv[1:]:
    data = open(fname).read()
    for match in re_with.finditer(data):
        if match.group('for'): with_for += 1
        total += 1

print 'with-for:', with_for, 'out of:', total, '(', 
with_for*100.0/total,'%)'

On my code, I get:

with-for: 38 out of: 47 ( 80.8510638298 %)

A few days ago, I proposed that a __throw__ method be added to context 
managers so that context managers could be used to capture common 
try/except usage patterns along with it's current ability to capture 
common try/finally patterns.

I am curious whether you see common try/except patterns that could be 
captured in a context manager so that you could simply write:

with my_except_handling(something) as x:
    many lines of code

rather than:

try:
   with something as f:
        many lines of code
except some_error:
    handle error

and be able to replace several occurrences of try/except/handle error 
with the same my_except_handling context manager?

-bruce frederiksen



More information about the Python-ideas mailing list