Your SlideShare is downloading. ×
The bones of a nice Python script
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

The bones of a nice Python script

2,752
views

Published on

Creating a useful boilerplate framework for command line Python scripts.

Creating a useful boilerplate framework for command line Python scripts.

Published in: Technology

0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,752
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
43
Comments
0
Likes
2
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Developing a nice template for new scripts
  • 2. #!/usr/bin/python import sys import random def scramble(word): if len(word) < 4: return word innards = list(word[1:-1]) random.shuffle(innards) return word[0] + ''.join(innards) + word[-1] while 1: line = sys.stdin.readline() if not line: break sys.stdout.write(' '.join([scramble(w) for w in line.split()]) + ' ') In the beginning
  • 3. Adding basic niceties #!/usr/bin/ env python # -*- coding: utf-8 -*- import sys import random def scramble(word): if len(word) < 4: return word innards = list(word[1:-1]) random.shuffle(innards) return word[0] + ''.join(innards) + word[-1] def _main(): while 1: line = sys.stdin.readline() if not line: break sys.stdout.write(' '.join([scramble(w) for w in line.split()]) + ' ') return 0 if __name__ == &quot;__main__&quot;: sys.exit(_main())
  • 4. stephenj@lords:~$ python Python 2.5.2 (r252:60911, Oct 5 2008, 19:24:49) [GCC 4.3.2] on linux2 Type &quot;help&quot;, &quot;copyright&quot;, &quot;credits&quot; or &quot;license&quot; for more information. >>> import scramble >>> scramble.scramble('scramble') 'srlacmbe' >>>
  • 5. from optparse import OptionParser ... def _main(filename=None): ... if __name__ == &quot;__main__&quot;: usage = &quot;usage: %prog [options] [filename]&quot; parser = OptionParser(usage=usage) parser.add_option('--profile', '-P', help = &quot;Print out profiling stats&quot;, action = 'store_true') parser.add_option('--test', '-t', help ='Run doctests', action = 'store_true') parser.add_option('--verbose', '-v', help ='print debugging output', action = 'store_true') (options, args) = parser.parse_args() # Assign non-flag arguments here. filename = None if len(args) > 0: filename = args[0]
  • 6. stephenj@lords:~$ python scramble.py -h Usage: scramble.py [options] [filename] Options: -h, --help show this help message and exit -P, --profile Print out profiling stats -t, --test Run doctests -v, --verbose print debugging output
  • 7. Tests are good def scramble(word): &quot;&quot;&quot; Returns a scrambled version if it is longer than 3 chars. Scrambling preserves the first and last characters. >>> scramble('a') 'a' >>> scramble('an') 'an' >>> scramble('the') 'the' >>> scramble('cart') in ['cart', 'crat'] True &quot;&quot;&quot; if len(word) < 4: return word innards = list(word[1:-1]) random.shuffle(innards) return word[0] + ''.join(innards) + word[-1] def _test(verbose=False): import doctest doctest.testmod(verbose=verbose)
  • 8. stephenj@lords:~$ python scramble.py --test --verbose Trying: scramble('a') Expecting: 'a' ok Trying: scramble('an') Expecting: 'an' ok Trying: scramble('the') Expecting: 'the' ok Trying: scramble('cart') in ['cart', 'crat'] Expecting: True ok 5 items had no tests: __main__ __main__._main __main__._profile_main __main__._test __main__.really_blurt 1 items passed all tests: 4 tests in __main__.scramble 4 tests in 6 items. 4 passed and 0 failed. Test passed. stephenj@lords:~$
  • 9. Now I'm a real boy Unix filter def _blurt(s, f): pass def _main(filename=None): f = sys.stdin if filename: try: f = file(filename) except Exception, ex: print &quot;Couldn't open file %s: %s&quot; % (filename, ex) return 1 while 1: line = f.readline() if not line: break _blurt(&quot;Original line was: %s&quot; % line) sys.stdout.write(' '.join([scramble(w) for w in line.split()]) + ' ') return 0 if __name__ == &quot;__main__&quot;: ... if options.verbose: def really_blurt(s, f=()): sys.stderr.write(s % f + ' ') _blurt = really_blurt ... if len(args) > 0: filename = args[0] _blurt(&quot;filename is %s&quot;, filename) sys.exit(_main(filename))
  • 10. Dealing with performance anxiety def _profile_main(filename=None): import cProfile, pstats prof = cProfile.Profile() ctx = &quot;&quot;&quot;_main(filename)&quot;&quot;&quot; prof = prof.runctx(ctx, globals(), locals()) stats = pstats.Stats(prof) stats.sort_stats(&quot;cumulative&quot;) stats.print_stats(10) ... if __name__ == &quot;__main__&quot;: ... if options.profile: _profile_main(filename) exit()
  • 11. Making use of our options stephenj@lords:~$ python scramble.py asdf Couldn't open file asdf: [Errno 2] No such file or directory: 'asdf' stephenj@lords:~$ echo $? 1 stephenj@lords:~$ echo &quot;You should probably be able to understand this&quot; | python scramble.py -v Original line was: You should probably be able to understand this You suhold pbrbolay be able to usedanrntd this stephenj@lords:~$ echo &quot;You should probably be able to understand this&quot; | python scramble.py -P You sluohd pbalbroy be albe to unrdentsad tihs 57 function calls in 0.000 CPU seconds Ordered by: internal time List reduced from 12 to 10 due to restriction <10> ncalls tottime percall cumtime percall filename:lineno(function) 5 0.000 0.000 0.000 0.000 /usr/lib/python2.5/random.py:250(shuffle) 8 0.000 0.000 0.000 0.000 scramble.py:16(scramble) 1 0.000 0.000 0.000 0.000 scramble.py:59(_main) 1 0.000 0.000 0.000 0.000 {method 'write' of 'file' objects} 17 0.000 0.000 0.000 0.000 {method 'random' of '_random.Random' objects} 2 0.000 0.000 0.000 0.000 {method 'readline' of 'file' objects} 13 0.000 0.000 0.000 0.000 {len} 6 0.000 0.000 0.000 0.000 {method 'join' of 'str' objects} 1 0.000 0.000 0.000 0.000 <string>:1(<module>) 1 0.000 0.000 0.000 0.000 {method 'split' of 'str' objects}
  • 12. #!/usr/bin/env python # -*- coding: utf-8 -*- import sys from optparse import OptionParser def _test(verbose=None): import doctest doctest.testmod(verbose=verbose) def _profile_main( filename=None ): import cProfile, pstats prof = cProfile.Profile() ctx = &quot;&quot;&quot;_main(filename)&quot;&quot;&quot; prof = prof.runctx(ctx, globals(), locals()) stats = pstats.Stats(prof) stats.sort_stats(&quot;time&quot;) stats.print_stats(10) def _blurt(s, f): pass def _main(filename=None): # YOUR CODE HERE return 0 if __name__ == &quot;__main__&quot;: usage = &quot;usage: %prog [options] [filename] &quot; parser = OptionParser(usage=usage) parser.add_option('--profile', '-P', help = &quot;Print out profiling stats&quot;, action = 'store_true') parser.add_option('--test', '-t', help ='Run doctests', action = 'store_true') parser.add_option('--verbose', '-v', help ='print debugging output', action = 'store_true') (options, args) = parser.parse_args() if options.verbose: def really_blurt(s, f=()): sys.stderr.write(s % f + ' ') _blurt = really_blurt # Assign non-flag arguments here. filename = args[0] if options.profile: _profile_main( filename ) exit() if options.test: _test(verbose=options.verbose) exit() sys.exit(_main( filename ))
  • 13. Original inspiration Guido's post and subsequent commentary http://www.artima.com/forums/flat.jsp?forum=106&thread=4829 Google app engine help http://code.google.com/appengine/kb/commontasks.html#profiling The scrambled text meme http://www.snopes.com/language/apocryph/cambridge.asp