PEP: 290 Title: Code Migration and Modernization Version: $Revision$ Last-Modified: $Date$ Author: python@rcn.com (Raymond D. Hettinger) Status: Active Type: Informational Created: 6-Jun-2002 Post-History: Abstract This PEP is a collection of procedures and ideas for updating Python applications when newer versions of Python are installed. The migration tips highlight possible areas of incompatibility and make suggestions on how to find and resolve those differences. The modernization procedures show how older code can be updated to take advantage of new language features. Rationale This repository of procedures serves as a catalog or checklist of known migration issues and procedures for addressing those issues. Migration issues can arise for several reasons. Some obsolete features are slowly deprecated according to the guidelines in PEP 4. Also, some code relies on undocumented behaviors which are subject to change between versions. Some code may rely on behavior which was subsequently shown to be a bug and that behavior changes when the bug is fixed. Modernization options arise when new versions of Python add features that allow improved clarity or higher performance than previously available. Guidelines for New Entries Developers with commit access may update the PEP directly. Others can send their ideas to a developer for possible inclusion. While a consistent format makes the repository easier to use, feel free to add or subtract sections to improve clarity. Grep patterns may be supplied as tool to help maintainers locate code for possible updates. However, fully automated search/replace style regular expressions are not recommended. Instead, each code fragment should be evaluated individually. The contra-indications section is the most important part of a new entry. It lists known situations where the update SHOULD NOT be applied. Modernization Procedures Pattern: if d.has_key(k): --> if k in d: Idea: For testing dictionary membership, use the 'in' keyword instead of the 'has_key()' method. Version: 2.2 or greater Benefits: The result is shorter and more readable. The style becomes consistent with tests for membership in lists. The result is slightly faster because has_key requires an attribute search and uses a relatively expensive CALL FUNCTION op code. Locating: grep has_key Contra-indications: 1. if dictlike.has_key(k) ## objects like shelve do not define __contains__() Pattern: for k in d.keys() --> for k in d for k in d.items() --> for k in d.iteritems() for k in d.values() --> for k in d.itervalues() Idea: Use the new iter methods for looping over dictionaries Version: 2.2 or greater Benefits: The iter methods are faster because the do not have to create a new list object with a complete copy of all of the keys, values, or items. Selecting only keys, items, or values as needed saves the time for creating throwaway object references and, in the case of items, saves a second hash look-up of the key. Contra-indications: 1. def getids(): return d.keys() ## do not change the return type 2. for k in dictlike.keys() ## objects like shelve do not define itermethods 3. k = d.keys(); j = k[:] ## iterators do not support slicing, sorting or other operations 4. for k in d.keys(): del[k] ## dict iterators prohibit modifying the dictionary Pattern: if v == None --> if v is None: if v != None --> if v is not None: Idea: Since there is only one None object, equality can be tested with identity. Version: All Benefits: Identity tests are slightly faster than equality tests. Also, some object types may overload comparison to be much slower. Locating: grep '== None' or grep '!= None' Pattern: os.stat("foo")[stat.ST_MTIME] --> os.stat("foo").st_mtime os.stat("foo")[stat.ST_MTIME] --> os.path.getmtime("foo") Idea: Replace stat contants or indices with new stat methods Version: 2.2 or greater Benefits: The methods are not order dependent and do not require an import of the stat module Locating: grep os.stat Pattern: import whrandom --> import random Idea: Replace deprecated module Version: 2.1 or greater Benefits: All random methods collected in one place Locating: grep whrandom Pattern: import types ; type(v, types.IntType) --> isinstance(v, int) type(s, types.StringTypes --> isinstance(s, basestring) Idea: The types module will likely to be deprecated in the future. Version: 2.3 or greater (basestring introduced in Py2.3) Benefits: May be slightly faster, avoid a deprecated feature. Locating: grep types *.py | grep import Pattern: import string ; string.method(s, ...) --> s.method(...) c in string.whitespace --> c.isspace() Idea: The string module will likely to be deprecated in the future. Version: 2.0 or greater Benefits: Slightly faster, avoid a deprecated feature. Locating: grep string *.py | grep import Pattern: NewError = 'NewError' --> class NewError(Exception): pass Idea: String exceptions are deprecated, derive from the Exception base class. Version: Any Benefits: Unlike the obsolete string exceptions, class exceptions all derive from another exception or the Exception base class. This allows meaningful groupings of exceptions. It also allows an "except Exception" clause to catch all exceptions. Locating: Use PyChecker Pattern: "foobar"[:3] == "foo" -> "foobar".startswith("foo") "foobar"[-3:] == "bar" -> "foobar".endswith("bar") Version: 2.0 or greater Benefits: Faster because no slice has to be created. Less risk of miscounting. References [1] PEP 4, Deprecation of Standard Modules http://www.python.org/peps/pep-0004.html Copyright This document has been placed in the public domain. Local Variables: mode: indented-text indent-tabs-mode: nil sentence-end-double-space: t fill-column: 70 End: