What Is New in Python 1.5
Python 1.5 (and its maintenance release 1.5.2) was the most widely deployed Python version of the late 1990s. It was the stable workhorse that popularized Python in system administration, data processing, and web CGI scripting. Key additions in the 1.5 series were packages (directories as module namespaces), assert statements, and the formalization of several module patterns that remain in the language today.
| Category | Change | Notes |
|---|---|---|
| Language | Packages -- directories with __init__.py as module namespaces |
PEP precursor; key to large Python projects |
| Language | assert statement for runtime assertions |
Replaces manual if not condition: raise AssertionError |
| Language | Private name mangling (__attr becomes _ClassName__attr) |
Basic encapsulation mechanism |
| Standard Library | Improved re module (regex + regsub still present but superseded) |
-- |
| Standard Library | pickle and cPickle for object serialization |
cPickle is a C implementation, ~100x faster |
| Standard Library | struct module for binary data packing/unpacking |
Essential for network protocol implementation |
| Standard Library | urllib, httplib, ftplib for basic network access |
-- |
| Platform | Windows installer; early COM/ActiveX support on Windows | Mark Hammond's win32 extensions |
Key Features of Python 1.5
Packages -- Multi-File Module Namespaces
Python 1.5 formalized packages: a directory containing an __init__.py file is treated as a package. Submodules are importable as package.submodule. This enabled the first large Python libraries to organize code across multiple files without namespace collisions.
# Directory layout:
# mypackage/
# __init__.py
# utils.py
# network.py
import mypackage.utils
from mypackage import network
from mypackage.network import connect
assert Statement
The assert statement provides a concise way to check invariants. It raises AssertionError if the condition is false. Assertions are disabled when Python is run with the -O (optimize) flag, so they should not be used for production input validation.
def divide(a, b):
assert b != 0, "Divisor must not be zero"
return a / b
Private Name Mangling
An attribute named __attr (two leading underscores, at most one trailing underscore) is automatically renamed to _ClassName__attr by Python. This provides weak encapsulation and avoids name clashes in subclasses, though it is not enforced security.
Why Python 1.5.2 Was So Important
Python 1.5.2 was the version that stayed in widespread use for years after its release. Many Linux distributions shipped it as the default Python interpreter into the early 2000s. It was the version Guido van Rossum used in his tutorials, and the version that introduced Python to much of the sysadmin and scientific computing community. When people say "Python was great in the late 90s," they usually mean 1.5.2.
FAQ
What is the difference between assert and a manual raise?
Functionally, assert condition, "msg" is equivalent to if __debug__: if not condition: raise AssertionError("msg"). The key difference is that assertions are silently disabled with python -O. This means assert is for development invariants and debugging, not for input validation or user-facing error handling.
Why do packages need __init__.py in early Python versions?
The __init__.py file serves two purposes: it marks the directory as a package, and it is executed when the package is first imported. Without it, Python would not recognize the directory as importable. Namespace packages (directories without __init__.py) were only introduced in Python 3.3.
Was cPickle always faster than pickle?
Yes, significantly -- typically 100x faster, since it is implemented in C. In Python 3, the pickle module automatically uses a C accelerator if available, so the explicit cPickle module was removed. In Python 2, you had to import cPickle explicitly to get the C version.
What happened to Python 1.5.2 systems?
Most Linux distributions that shipped 1.5.2 as their system Python migrated to 2.x during 2002-2005. Red Hat and Fedora, Debian, and SuSE all eventually shipped Python 2.3 or 2.4 as the default. Using Python 1.5.2 in any context today would be a significant maintenance and security risk.
How was private name mangling different from true private access?
Name mangling is not access control -- the mangled name is accessible as obj._ClassName__attr from outside the class. It only prevents accidental access and name clashes in deep inheritance hierarchies. Python's philosophy has always been "we're all consenting adults" -- the single underscore convention (_private) is the more common and idiomatic signal of a non-public attribute.