mirror of https://github.com/python/cpython.git
Issue #23921: Standardized documentation whitespace formatting.
Original patch by James Edwards.
This commit is contained in:
parent
387235085c
commit
dba903993a
|
@ -1907,9 +1907,9 @@ Subclasses of :class:`Command` must define the following methods.
|
||||||
that is designed to run with both Python 2.x and 3.x, add::
|
that is designed to run with both Python 2.x and 3.x, add::
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from distutils.command.build_py import build_py_2to3 as build_py
|
from distutils.command.build_py import build_py_2to3 as build_py
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from distutils.command.build_py import build_py
|
from distutils.command.build_py import build_py
|
||||||
|
|
||||||
to your setup.py, and later::
|
to your setup.py, and later::
|
||||||
|
|
||||||
|
|
|
@ -158,7 +158,7 @@ where in Python you're forced to write this::
|
||||||
line = f.readline()
|
line = f.readline()
|
||||||
if not line:
|
if not line:
|
||||||
break
|
break
|
||||||
... # do something with line
|
... # do something with line
|
||||||
|
|
||||||
The reason for not allowing assignment in Python expressions is a common,
|
The reason for not allowing assignment in Python expressions is a common,
|
||||||
hard-to-find bug in those other languages, caused by this construct:
|
hard-to-find bug in those other languages, caused by this construct:
|
||||||
|
@ -190,7 +190,7 @@ generally less robust than the "while True" solution::
|
||||||
|
|
||||||
line = f.readline()
|
line = f.readline()
|
||||||
while line:
|
while line:
|
||||||
... # do something with line...
|
... # do something with line...
|
||||||
line = f.readline()
|
line = f.readline()
|
||||||
|
|
||||||
The problem with this is that if you change your mind about exactly how you get
|
The problem with this is that if you change your mind about exactly how you get
|
||||||
|
@ -203,7 +203,7 @@ objects using the ``for`` statement. For example, :term:`file objects
|
||||||
<file object>` support the iterator protocol, so you can write simply::
|
<file object>` support the iterator protocol, so you can write simply::
|
||||||
|
|
||||||
for line in f:
|
for line in f:
|
||||||
... # do something with line...
|
... # do something with line...
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -577,8 +577,10 @@ other structure). ::
|
||||||
class ListWrapper:
|
class ListWrapper:
|
||||||
def __init__(self, the_list):
|
def __init__(self, the_list):
|
||||||
self.the_list = the_list
|
self.the_list = the_list
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return self.the_list == other.the_list
|
return self.the_list == other.the_list
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
l = self.the_list
|
l = self.the_list
|
||||||
result = 98767 - len(l)*555
|
result = 98767 - len(l)*555
|
||||||
|
@ -619,7 +621,7 @@ it and returns it. For example, here's how to iterate over the keys of a
|
||||||
dictionary in sorted order::
|
dictionary in sorted order::
|
||||||
|
|
||||||
for key in sorted(mydict):
|
for key in sorted(mydict):
|
||||||
... # do whatever with mydict[key]...
|
... # do whatever with mydict[key]...
|
||||||
|
|
||||||
|
|
||||||
How do you specify and enforce an interface spec in Python?
|
How do you specify and enforce an interface spec in Python?
|
||||||
|
@ -675,11 +677,11 @@ languages. For example::
|
||||||
class label(Exception): pass # declare a label
|
class label(Exception): pass # declare a label
|
||||||
|
|
||||||
try:
|
try:
|
||||||
...
|
...
|
||||||
if condition: raise label() # goto label
|
if condition: raise label() # goto label
|
||||||
...
|
...
|
||||||
except label: # where to goto
|
except label: # where to goto
|
||||||
pass
|
pass
|
||||||
...
|
...
|
||||||
|
|
||||||
This doesn't allow you to jump into the middle of a loop, but that's usually
|
This doesn't allow you to jump into the middle of a loop, but that's usually
|
||||||
|
|
|
@ -257,7 +257,8 @@ all the threads to finish::
|
||||||
import threading, time
|
import threading, time
|
||||||
|
|
||||||
def thread_task(name, n):
|
def thread_task(name, n):
|
||||||
for i in range(n): print(name, i)
|
for i in range(n):
|
||||||
|
print(name, i)
|
||||||
|
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
T = threading.Thread(target=thread_task, args=(str(i), i))
|
T = threading.Thread(target=thread_task, args=(str(i), i))
|
||||||
|
@ -273,7 +274,8 @@ A simple fix is to add a tiny sleep to the start of the run function::
|
||||||
|
|
||||||
def thread_task(name, n):
|
def thread_task(name, n):
|
||||||
time.sleep(0.001) # <--------------------!
|
time.sleep(0.001) # <--------------------!
|
||||||
for i in range(n): print(name, i)
|
for i in range(n):
|
||||||
|
print(name, i)
|
||||||
|
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
T = threading.Thread(target=thread_task, args=(str(i), i))
|
T = threading.Thread(target=thread_task, args=(str(i), i))
|
||||||
|
@ -502,8 +504,8 @@ in big-endian format from a file::
|
||||||
import struct
|
import struct
|
||||||
|
|
||||||
with open(filename, "rb") as f:
|
with open(filename, "rb") as f:
|
||||||
s = f.read(8)
|
s = f.read(8)
|
||||||
x, y, z = struct.unpack(">hhl", s)
|
x, y, z = struct.unpack(">hhl", s)
|
||||||
|
|
||||||
The '>' in the format string forces big-endian data; the letter 'h' reads one
|
The '>' in the format string forces big-endian data; the letter 'h' reads one
|
||||||
"short integer" (2 bytes), and 'l' reads one "long integer" (4 bytes) from the
|
"short integer" (2 bytes), and 'l' reads one "long integer" (4 bytes) from the
|
||||||
|
@ -681,10 +683,10 @@ Yes. Here's a simple example that uses urllib.request::
|
||||||
|
|
||||||
import urllib.request
|
import urllib.request
|
||||||
|
|
||||||
### build the query string
|
# build the query string
|
||||||
qs = "First=Josephine&MI=Q&Last=Public"
|
qs = "First=Josephine&MI=Q&Last=Public"
|
||||||
|
|
||||||
### connect and send the server a path
|
# connect and send the server a path
|
||||||
req = urllib.request.urlopen('http://www.some-server.out-there'
|
req = urllib.request.urlopen('http://www.some-server.out-there'
|
||||||
'/cgi-bin/some-cgi-script', data=qs)
|
'/cgi-bin/some-cgi-script', data=qs)
|
||||||
with req:
|
with req:
|
||||||
|
@ -740,8 +742,9 @@ varies between systems; sometimes it is ``/usr/lib/sendmail``, sometimes
|
||||||
``/usr/sbin/sendmail``. The sendmail manual page will help you out. Here's
|
``/usr/sbin/sendmail``. The sendmail manual page will help you out. Here's
|
||||||
some sample code::
|
some sample code::
|
||||||
|
|
||||||
SENDMAIL = "/usr/sbin/sendmail" # sendmail location
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
SENDMAIL = "/usr/sbin/sendmail" # sendmail location
|
||||||
p = os.popen("%s -t -i" % SENDMAIL, "w")
|
p = os.popen("%s -t -i" % SENDMAIL, "w")
|
||||||
p.write("To: receiver@example.com\n")
|
p.write("To: receiver@example.com\n")
|
||||||
p.write("Subject: test\n")
|
p.write("Subject: test\n")
|
||||||
|
|
|
@ -207,7 +207,7 @@ functions), e.g.::
|
||||||
|
|
||||||
>>> squares = []
|
>>> squares = []
|
||||||
>>> for x in range(5):
|
>>> for x in range(5):
|
||||||
... squares.append(lambda: x**2)
|
... squares.append(lambda: x**2)
|
||||||
|
|
||||||
This gives you a list that contains 5 lambdas that calculate ``x**2``. You
|
This gives you a list that contains 5 lambdas that calculate ``x**2``. You
|
||||||
might expect that, when called, they would return, respectively, ``0``, ``1``,
|
might expect that, when called, they would return, respectively, ``0``, ``1``,
|
||||||
|
@ -234,7 +234,7 @@ lambdas, so that they don't rely on the value of the global ``x``::
|
||||||
|
|
||||||
>>> squares = []
|
>>> squares = []
|
||||||
>>> for x in range(5):
|
>>> for x in range(5):
|
||||||
... squares.append(lambda n=x: n**2)
|
... squares.append(lambda n=x: n**2)
|
||||||
|
|
||||||
Here, ``n=x`` creates a new variable ``n`` local to the lambda and computed
|
Here, ``n=x`` creates a new variable ``n`` local to the lambda and computed
|
||||||
when the lambda is defined so that it has the same value that ``x`` had at
|
when the lambda is defined so that it has the same value that ``x`` had at
|
||||||
|
@ -539,7 +539,7 @@ desired effect in a number of ways.
|
||||||
args['a'] = 'new-value' # args is a mutable dictionary
|
args['a'] = 'new-value' # args is a mutable dictionary
|
||||||
args['b'] = args['b'] + 1 # change it in-place
|
args['b'] = args['b'] + 1 # change it in-place
|
||||||
|
|
||||||
args = {'a':' old-value', 'b': 99}
|
args = {'a': 'old-value', 'b': 99}
|
||||||
func3(args)
|
func3(args)
|
||||||
print(args['a'], args['b'])
|
print(args['a'], args['b'])
|
||||||
|
|
||||||
|
@ -655,16 +655,15 @@ Essentially, assignment always binds a name to a value; The same is true of
|
||||||
``def`` and ``class`` statements, but in that case the value is a
|
``def`` and ``class`` statements, but in that case the value is a
|
||||||
callable. Consider the following code::
|
callable. Consider the following code::
|
||||||
|
|
||||||
class A:
|
>>> class A:
|
||||||
pass
|
... pass
|
||||||
|
...
|
||||||
B = A
|
>>> B = A
|
||||||
|
>>> a = B()
|
||||||
a = B()
|
>>> b = a
|
||||||
b = a
|
>>> print(b)
|
||||||
print(b)
|
|
||||||
<__main__.A object at 0x16D07CC>
|
<__main__.A object at 0x16D07CC>
|
||||||
print(a)
|
>>> print(a)
|
||||||
<__main__.A object at 0x16D07CC>
|
<__main__.A object at 0x16D07CC>
|
||||||
|
|
||||||
Arguably the class has a name: even though it is bound to two names and invoked
|
Arguably the class has a name: even though it is bound to two names and invoked
|
||||||
|
@ -1099,7 +1098,7 @@ How do I iterate over a sequence in reverse order?
|
||||||
Use the :func:`reversed` built-in function, which is new in Python 2.4::
|
Use the :func:`reversed` built-in function, which is new in Python 2.4::
|
||||||
|
|
||||||
for x in reversed(sequence):
|
for x in reversed(sequence):
|
||||||
... # do something with x...
|
... # do something with x ...
|
||||||
|
|
||||||
This won't touch your original sequence, but build a new copy with reversed
|
This won't touch your original sequence, but build a new copy with reversed
|
||||||
order to iterate over.
|
order to iterate over.
|
||||||
|
@ -1107,7 +1106,7 @@ order to iterate over.
|
||||||
With Python 2.3, you can use an extended slice syntax::
|
With Python 2.3, you can use an extended slice syntax::
|
||||||
|
|
||||||
for x in sequence[::-1]:
|
for x in sequence[::-1]:
|
||||||
... # do something with x...
|
... # do something with x ...
|
||||||
|
|
||||||
|
|
||||||
How do you remove duplicates from a list?
|
How do you remove duplicates from a list?
|
||||||
|
@ -1405,7 +1404,7 @@ A method is a function on some object ``x`` that you normally call as
|
||||||
definition::
|
definition::
|
||||||
|
|
||||||
class C:
|
class C:
|
||||||
def meth (self, arg):
|
def meth(self, arg):
|
||||||
return arg * 2 + self.attribute
|
return arg * 2 + self.attribute
|
||||||
|
|
||||||
|
|
||||||
|
@ -1438,9 +1437,9 @@ that does something::
|
||||||
|
|
||||||
def search(obj):
|
def search(obj):
|
||||||
if isinstance(obj, Mailbox):
|
if isinstance(obj, Mailbox):
|
||||||
# ... code to search a mailbox
|
... # code to search a mailbox
|
||||||
elif isinstance(obj, Document):
|
elif isinstance(obj, Document):
|
||||||
# ... code to search a document
|
... # code to search a document
|
||||||
elif ...
|
elif ...
|
||||||
|
|
||||||
A better approach is to define a ``search()`` method on all the classes and just
|
A better approach is to define a ``search()`` method on all the classes and just
|
||||||
|
@ -1448,11 +1447,11 @@ call it::
|
||||||
|
|
||||||
class Mailbox:
|
class Mailbox:
|
||||||
def search(self):
|
def search(self):
|
||||||
# ... code to search a mailbox
|
... # code to search a mailbox
|
||||||
|
|
||||||
class Document:
|
class Document:
|
||||||
def search(self):
|
def search(self):
|
||||||
# ... code to search a document
|
... # code to search a document
|
||||||
|
|
||||||
obj.search()
|
obj.search()
|
||||||
|
|
||||||
|
@ -1509,7 +1508,7 @@ How do I call a method defined in a base class from a derived class that overrid
|
||||||
Use the built-in :func:`super` function::
|
Use the built-in :func:`super` function::
|
||||||
|
|
||||||
class Derived(Base):
|
class Derived(Base):
|
||||||
def meth (self):
|
def meth(self):
|
||||||
super(Derived, self).meth()
|
super(Derived, self).meth()
|
||||||
|
|
||||||
For version prior to 3.0, you may be using classic classes: For a class
|
For version prior to 3.0, you may be using classic classes: For a class
|
||||||
|
|
|
@ -104,7 +104,7 @@ like::
|
||||||
"Emulate type_getattro() in Objects/typeobject.c"
|
"Emulate type_getattro() in Objects/typeobject.c"
|
||||||
v = object.__getattribute__(self, key)
|
v = object.__getattribute__(self, key)
|
||||||
if hasattr(v, '__get__'):
|
if hasattr(v, '__get__'):
|
||||||
return v.__get__(None, self)
|
return v.__get__(None, self)
|
||||||
return v
|
return v
|
||||||
|
|
||||||
The important points to remember are:
|
The important points to remember are:
|
||||||
|
@ -163,9 +163,9 @@ descriptor is useful for monitoring just a few chosen attributes::
|
||||||
self.val = val
|
self.val = val
|
||||||
|
|
||||||
>>> class MyClass(object):
|
>>> class MyClass(object):
|
||||||
x = RevealAccess(10, 'var "x"')
|
... x = RevealAccess(10, 'var "x"')
|
||||||
y = 5
|
... y = 5
|
||||||
|
...
|
||||||
>>> m = MyClass()
|
>>> m = MyClass()
|
||||||
>>> m.x
|
>>> m.x
|
||||||
Retrieving var "x"
|
Retrieving var "x"
|
||||||
|
@ -287,15 +287,15 @@ this::
|
||||||
Running the interpreter shows how the function descriptor works in practice::
|
Running the interpreter shows how the function descriptor works in practice::
|
||||||
|
|
||||||
>>> class D(object):
|
>>> class D(object):
|
||||||
def f(self, x):
|
... def f(self, x):
|
||||||
return x
|
... return x
|
||||||
|
...
|
||||||
>>> d = D()
|
>>> d = D()
|
||||||
>>> D.__dict__['f'] # Stored internally as a function
|
>>> D.__dict__['f'] # Stored internally as a function
|
||||||
<function f at 0x00C45070>
|
<function f at 0x00C45070>
|
||||||
>>> D.f # Get from a class becomes an unbound method
|
>>> D.f # Get from a class becomes an unbound method
|
||||||
<unbound method D.f>
|
<unbound method D.f>
|
||||||
>>> d.f # Get from an instance becomes a bound method
|
>>> d.f # Get from an instance becomes a bound method
|
||||||
<bound method D.f of <__main__.D object at 0x00B18C90>>
|
<bound method D.f of <__main__.D object at 0x00B18C90>>
|
||||||
|
|
||||||
The output suggests that bound and unbound methods are two different types.
|
The output suggests that bound and unbound methods are two different types.
|
||||||
|
@ -358,10 +358,10 @@ Since staticmethods return the underlying function with no changes, the example
|
||||||
calls are unexciting::
|
calls are unexciting::
|
||||||
|
|
||||||
>>> class E(object):
|
>>> class E(object):
|
||||||
def f(x):
|
... def f(x):
|
||||||
print(x)
|
... print(x)
|
||||||
f = staticmethod(f)
|
... f = staticmethod(f)
|
||||||
|
...
|
||||||
>>> print(E.f(3))
|
>>> print(E.f(3))
|
||||||
3
|
3
|
||||||
>>> print(E().f(3))
|
>>> print(E().f(3))
|
||||||
|
@ -371,23 +371,23 @@ Using the non-data descriptor protocol, a pure Python version of
|
||||||
:func:`staticmethod` would look like this::
|
:func:`staticmethod` would look like this::
|
||||||
|
|
||||||
class StaticMethod(object):
|
class StaticMethod(object):
|
||||||
"Emulate PyStaticMethod_Type() in Objects/funcobject.c"
|
"Emulate PyStaticMethod_Type() in Objects/funcobject.c"
|
||||||
|
|
||||||
def __init__(self, f):
|
def __init__(self, f):
|
||||||
self.f = f
|
self.f = f
|
||||||
|
|
||||||
def __get__(self, obj, objtype=None):
|
def __get__(self, obj, objtype=None):
|
||||||
return self.f
|
return self.f
|
||||||
|
|
||||||
Unlike static methods, class methods prepend the class reference to the
|
Unlike static methods, class methods prepend the class reference to the
|
||||||
argument list before calling the function. This format is the same
|
argument list before calling the function. This format is the same
|
||||||
for whether the caller is an object or a class::
|
for whether the caller is an object or a class::
|
||||||
|
|
||||||
>>> class E(object):
|
>>> class E(object):
|
||||||
def f(klass, x):
|
... def f(klass, x):
|
||||||
return klass.__name__, x
|
... return klass.__name__, x
|
||||||
f = classmethod(f)
|
... f = classmethod(f)
|
||||||
|
...
|
||||||
>>> print(E.f(3))
|
>>> print(E.f(3))
|
||||||
('E', 3)
|
('E', 3)
|
||||||
>>> print(E().f(3))
|
>>> print(E().f(3))
|
||||||
|
@ -419,15 +419,15 @@ Using the non-data descriptor protocol, a pure Python version of
|
||||||
:func:`classmethod` would look like this::
|
:func:`classmethod` would look like this::
|
||||||
|
|
||||||
class ClassMethod(object):
|
class ClassMethod(object):
|
||||||
"Emulate PyClassMethod_Type() in Objects/funcobject.c"
|
"Emulate PyClassMethod_Type() in Objects/funcobject.c"
|
||||||
|
|
||||||
def __init__(self, f):
|
def __init__(self, f):
|
||||||
self.f = f
|
self.f = f
|
||||||
|
|
||||||
def __get__(self, obj, klass=None):
|
def __get__(self, obj, klass=None):
|
||||||
if klass is None:
|
if klass is None:
|
||||||
klass = type(obj)
|
klass = type(obj)
|
||||||
def newfunc(*args):
|
def newfunc(*args):
|
||||||
return self.f(klass, *args)
|
return self.f(klass, *args)
|
||||||
return newfunc
|
return newfunc
|
||||||
|
|
||||||
|
|
|
@ -395,14 +395,14 @@ equivalent to the following Python code::
|
||||||
continue # Skip this element
|
continue # Skip this element
|
||||||
for expr2 in sequence2:
|
for expr2 in sequence2:
|
||||||
if not (condition2):
|
if not (condition2):
|
||||||
continue # Skip this element
|
continue # Skip this element
|
||||||
...
|
...
|
||||||
for exprN in sequenceN:
|
for exprN in sequenceN:
|
||||||
if not (conditionN):
|
if not (conditionN):
|
||||||
continue # Skip this element
|
continue # Skip this element
|
||||||
|
|
||||||
# Output the value of
|
# Output the value of
|
||||||
# the expression.
|
# the expression.
|
||||||
|
|
||||||
This means that when there are multiple ``for...in`` clauses but no ``if``
|
This means that when there are multiple ``for...in`` clauses but no ``if``
|
||||||
clauses, the length of the resulting output will be equal to the product of the
|
clauses, the length of the resulting output will be equal to the product of the
|
||||||
|
|
|
@ -63,6 +63,7 @@ Here is the auxiliary module::
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.logger = logging.getLogger('spam_application.auxiliary.Auxiliary')
|
self.logger = logging.getLogger('spam_application.auxiliary.Auxiliary')
|
||||||
self.logger.info('creating an instance of Auxiliary')
|
self.logger.info('creating an instance of Auxiliary')
|
||||||
|
|
||||||
def do_something(self):
|
def do_something(self):
|
||||||
self.logger.info('doing something')
|
self.logger.info('doing something')
|
||||||
a = 1 + 1
|
a = 1 + 1
|
||||||
|
@ -360,7 +361,7 @@ classes, which would eat up one thread per handler for no particular benefit.
|
||||||
|
|
||||||
An example of using these two classes follows (imports omitted)::
|
An example of using these two classes follows (imports omitted)::
|
||||||
|
|
||||||
que = queue.Queue(-1) # no limit on size
|
que = queue.Queue(-1) # no limit on size
|
||||||
queue_handler = QueueHandler(que)
|
queue_handler = QueueHandler(que)
|
||||||
handler = logging.StreamHandler()
|
handler = logging.StreamHandler()
|
||||||
listener = QueueListener(que, handler)
|
listener = QueueListener(que, handler)
|
||||||
|
@ -656,21 +657,21 @@ script::
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
levels = (logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL)
|
levels = (logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL)
|
||||||
logging.basicConfig(level=logging.DEBUG,
|
logging.basicConfig(level=logging.DEBUG,
|
||||||
format='%(asctime)-15s %(name)-5s %(levelname)-8s IP: %(ip)-15s User: %(user)-8s %(message)s')
|
format='%(asctime)-15s %(name)-5s %(levelname)-8s IP: %(ip)-15s User: %(user)-8s %(message)s')
|
||||||
a1 = logging.getLogger('a.b.c')
|
a1 = logging.getLogger('a.b.c')
|
||||||
a2 = logging.getLogger('d.e.f')
|
a2 = logging.getLogger('d.e.f')
|
||||||
|
|
||||||
f = ContextFilter()
|
f = ContextFilter()
|
||||||
a1.addFilter(f)
|
a1.addFilter(f)
|
||||||
a2.addFilter(f)
|
a2.addFilter(f)
|
||||||
a1.debug('A debug message')
|
a1.debug('A debug message')
|
||||||
a1.info('An info message with %s', 'some parameters')
|
a1.info('An info message with %s', 'some parameters')
|
||||||
for x in range(10):
|
for x in range(10):
|
||||||
lvl = choice(levels)
|
lvl = choice(levels)
|
||||||
lvlname = logging.getLevelName(lvl)
|
lvlname = logging.getLevelName(lvl)
|
||||||
a2.log(lvl, 'A message at %s level with %d %s', lvlname, 2, 'parameters')
|
a2.log(lvl, 'A message at %s level with %d %s', lvlname, 2, 'parameters')
|
||||||
|
|
||||||
which, when run, produces something like::
|
which, when run, produces something like::
|
||||||
|
|
||||||
|
@ -764,10 +765,10 @@ the basis for code meeting your own specific requirements::
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
record = queue.get()
|
record = queue.get()
|
||||||
if record is None: # We send this as a sentinel to tell the listener to quit.
|
if record is None: # We send this as a sentinel to tell the listener to quit.
|
||||||
break
|
break
|
||||||
logger = logging.getLogger(record.name)
|
logger = logging.getLogger(record.name)
|
||||||
logger.handle(record) # No level or filter logic applied - just do it!
|
logger.handle(record) # No level or filter logic applied - just do it!
|
||||||
except Exception:
|
except Exception:
|
||||||
import sys, traceback
|
import sys, traceback
|
||||||
print('Whoops! Problem:', file=sys.stderr)
|
print('Whoops! Problem:', file=sys.stderr)
|
||||||
|
@ -790,10 +791,11 @@ the basis for code meeting your own specific requirements::
|
||||||
# Note that on Windows you can't rely on fork semantics, so each process
|
# Note that on Windows you can't rely on fork semantics, so each process
|
||||||
# will run the logging configuration code when it starts.
|
# will run the logging configuration code when it starts.
|
||||||
def worker_configurer(queue):
|
def worker_configurer(queue):
|
||||||
h = logging.handlers.QueueHandler(queue) # Just the one handler needed
|
h = logging.handlers.QueueHandler(queue) # Just the one handler needed
|
||||||
root = logging.getLogger()
|
root = logging.getLogger()
|
||||||
root.addHandler(h)
|
root.addHandler(h)
|
||||||
root.setLevel(logging.DEBUG) # send all messages, for demo; no other level or filter logic applied.
|
# send all messages, for demo; no other level or filter logic applied.
|
||||||
|
root.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
# This is the worker process top-level loop, which just logs ten events with
|
# This is the worker process top-level loop, which just logs ten events with
|
||||||
# random intervening delays before terminating.
|
# random intervening delays before terminating.
|
||||||
|
@ -821,7 +823,7 @@ the basis for code meeting your own specific requirements::
|
||||||
workers = []
|
workers = []
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
worker = multiprocessing.Process(target=worker_process,
|
worker = multiprocessing.Process(target=worker_process,
|
||||||
args=(queue, worker_configurer))
|
args=(queue, worker_configurer))
|
||||||
workers.append(worker)
|
workers.append(worker)
|
||||||
worker.start()
|
worker.start()
|
||||||
for w in workers:
|
for w in workers:
|
||||||
|
@ -1245,12 +1247,12 @@ You can use a :class:`QueueHandler` subclass to send messages to other kinds
|
||||||
of queues, for example a ZeroMQ 'publish' socket. In the example below,the
|
of queues, for example a ZeroMQ 'publish' socket. In the example below,the
|
||||||
socket is created separately and passed to the handler (as its 'queue')::
|
socket is created separately and passed to the handler (as its 'queue')::
|
||||||
|
|
||||||
import zmq # using pyzmq, the Python binding for ZeroMQ
|
import zmq # using pyzmq, the Python binding for ZeroMQ
|
||||||
import json # for serializing records portably
|
import json # for serializing records portably
|
||||||
|
|
||||||
ctx = zmq.Context()
|
ctx = zmq.Context()
|
||||||
sock = zmq.Socket(ctx, zmq.PUB) # or zmq.PUSH, or other suitable value
|
sock = zmq.Socket(ctx, zmq.PUB) # or zmq.PUSH, or other suitable value
|
||||||
sock.bind('tcp://*:5556') # or wherever
|
sock.bind('tcp://*:5556') # or wherever
|
||||||
|
|
||||||
class ZeroMQSocketHandler(QueueHandler):
|
class ZeroMQSocketHandler(QueueHandler):
|
||||||
def enqueue(self, record):
|
def enqueue(self, record):
|
||||||
|
@ -1288,7 +1290,7 @@ of queues, for example a ZeroMQ 'subscribe' socket. Here's an example::
|
||||||
def __init__(self, uri, *handlers, **kwargs):
|
def __init__(self, uri, *handlers, **kwargs):
|
||||||
self.ctx = kwargs.get('ctx') or zmq.Context()
|
self.ctx = kwargs.get('ctx') or zmq.Context()
|
||||||
socket = zmq.Socket(self.ctx, zmq.SUB)
|
socket = zmq.Socket(self.ctx, zmq.SUB)
|
||||||
socket.setsockopt(zmq.SUBSCRIBE, '') # subscribe to everything
|
socket.setsockopt(zmq.SUBSCRIBE, '') # subscribe to everything
|
||||||
socket.connect(uri)
|
socket.connect(uri)
|
||||||
|
|
||||||
def dequeue(self):
|
def dequeue(self):
|
||||||
|
@ -2116,7 +2118,7 @@ class, as shown in the following example::
|
||||||
Format an exception so that it prints on a single line.
|
Format an exception so that it prints on a single line.
|
||||||
"""
|
"""
|
||||||
result = super(OneLineExceptionFormatter, self).formatException(exc_info)
|
result = super(OneLineExceptionFormatter, self).formatException(exc_info)
|
||||||
return repr(result) # or format into one line however you want to
|
return repr(result) # or format into one line however you want to
|
||||||
|
|
||||||
def format(self, record):
|
def format(self, record):
|
||||||
s = super(OneLineExceptionFormatter, self).format(record)
|
s = super(OneLineExceptionFormatter, self).format(record)
|
||||||
|
|
|
@ -103,8 +103,8 @@ A simple example
|
||||||
A very simple example is::
|
A very simple example is::
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
logging.warning('Watch out!') # will print a message to the console
|
logging.warning('Watch out!') # will print a message to the console
|
||||||
logging.info('I told you so') # will not print anything
|
logging.info('I told you so') # will not print anything
|
||||||
|
|
||||||
If you type these lines into a script and run it, you'll see::
|
If you type these lines into a script and run it, you'll see::
|
||||||
|
|
||||||
|
|
|
@ -1115,19 +1115,19 @@ which can be either a string or a function, and the string to be processed.
|
||||||
Here's a simple example of using the :meth:`sub` method. It replaces colour
|
Here's a simple example of using the :meth:`sub` method. It replaces colour
|
||||||
names with the word ``colour``::
|
names with the word ``colour``::
|
||||||
|
|
||||||
>>> p = re.compile( '(blue|white|red)')
|
>>> p = re.compile('(blue|white|red)')
|
||||||
>>> p.sub( 'colour', 'blue socks and red shoes')
|
>>> p.sub('colour', 'blue socks and red shoes')
|
||||||
'colour socks and colour shoes'
|
'colour socks and colour shoes'
|
||||||
>>> p.sub( 'colour', 'blue socks and red shoes', count=1)
|
>>> p.sub('colour', 'blue socks and red shoes', count=1)
|
||||||
'colour socks and red shoes'
|
'colour socks and red shoes'
|
||||||
|
|
||||||
The :meth:`subn` method does the same work, but returns a 2-tuple containing the
|
The :meth:`subn` method does the same work, but returns a 2-tuple containing the
|
||||||
new string value and the number of replacements that were performed::
|
new string value and the number of replacements that were performed::
|
||||||
|
|
||||||
>>> p = re.compile( '(blue|white|red)')
|
>>> p = re.compile('(blue|white|red)')
|
||||||
>>> p.subn( 'colour', 'blue socks and red shoes')
|
>>> p.subn('colour', 'blue socks and red shoes')
|
||||||
('colour socks and colour shoes', 2)
|
('colour socks and colour shoes', 2)
|
||||||
>>> p.subn( 'colour', 'no colours at all')
|
>>> p.subn('colour', 'no colours at all')
|
||||||
('no colours at all', 0)
|
('no colours at all', 0)
|
||||||
|
|
||||||
Empty matches are replaced only when they're not adjacent to a previous match.
|
Empty matches are replaced only when they're not adjacent to a previous match.
|
||||||
|
|
|
@ -687,7 +687,7 @@ with the ``surrogateescape`` error handler::
|
||||||
# make changes to the string 'data'
|
# make changes to the string 'data'
|
||||||
|
|
||||||
with open(fname + '.new', 'w',
|
with open(fname + '.new', 'w',
|
||||||
encoding="ascii", errors="surrogateescape") as f:
|
encoding="ascii", errors="surrogateescape") as f:
|
||||||
f.write(data)
|
f.write(data)
|
||||||
|
|
||||||
The ``surrogateescape`` error handler will decode any non-ASCII bytes
|
The ``surrogateescape`` error handler will decode any non-ASCII bytes
|
||||||
|
|
|
@ -175,10 +175,10 @@ Explorer [#]_. ::
|
||||||
|
|
||||||
url = 'http://www.someserver.com/cgi-bin/register.cgi'
|
url = 'http://www.someserver.com/cgi-bin/register.cgi'
|
||||||
user_agent = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)'
|
user_agent = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)'
|
||||||
values = {'name' : 'Michael Foord',
|
values = {'name': 'Michael Foord',
|
||||||
'location' : 'Northampton',
|
'location': 'Northampton',
|
||||||
'language' : 'Python' }
|
'language': 'Python' }
|
||||||
headers = { 'User-Agent' : user_agent }
|
headers = {'User-Agent': user_agent}
|
||||||
|
|
||||||
data = urllib.parse.urlencode(values)
|
data = urllib.parse.urlencode(values)
|
||||||
data = data.encode('ascii')
|
data = data.encode('ascii')
|
||||||
|
@ -215,7 +215,7 @@ e.g. ::
|
||||||
>>> req = urllib.request.Request('http://www.pretend_server.org')
|
>>> req = urllib.request.Request('http://www.pretend_server.org')
|
||||||
>>> try: urllib.request.urlopen(req)
|
>>> try: urllib.request.urlopen(req)
|
||||||
... except urllib.error.URLError as e:
|
... except urllib.error.URLError as e:
|
||||||
... print(e.reason) #doctest: +SKIP
|
... print(e.reason) #doctest: +SKIP
|
||||||
...
|
...
|
||||||
(4, 'getaddrinfo failed')
|
(4, 'getaddrinfo failed')
|
||||||
|
|
||||||
|
@ -372,7 +372,7 @@ Number 2
|
||||||
::
|
::
|
||||||
|
|
||||||
from urllib.request import Request, urlopen
|
from urllib.request import Request, urlopen
|
||||||
from urllib.error import URLError
|
from urllib.error import URLError
|
||||||
req = Request(someurl)
|
req = Request(someurl)
|
||||||
try:
|
try:
|
||||||
response = urlopen(req)
|
response = urlopen(req)
|
||||||
|
|
|
@ -35,10 +35,10 @@ produces either the sum or the max::
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description='Process some integers.')
|
parser = argparse.ArgumentParser(description='Process some integers.')
|
||||||
parser.add_argument('integers', metavar='N', type=int, nargs='+',
|
parser.add_argument('integers', metavar='N', type=int, nargs='+',
|
||||||
help='an integer for the accumulator')
|
help='an integer for the accumulator')
|
||||||
parser.add_argument('--sum', dest='accumulate', action='store_const',
|
parser.add_argument('--sum', dest='accumulate', action='store_const',
|
||||||
const=sum, default=max,
|
const=sum, default=max,
|
||||||
help='sum the integers (default: find the max)')
|
help='sum the integers (default: find the max)')
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
print(args.accumulate(args.integers))
|
print(args.accumulate(args.integers))
|
||||||
|
@ -488,7 +488,7 @@ specified characters will be treated as files, and will be replaced by the
|
||||||
arguments they contain. For example::
|
arguments they contain. For example::
|
||||||
|
|
||||||
>>> with open('args.txt', 'w') as fp:
|
>>> with open('args.txt', 'w') as fp:
|
||||||
... fp.write('-f\nbar')
|
... fp.write('-f\nbar')
|
||||||
>>> parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
|
>>> parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
|
||||||
>>> parser.add_argument('-f')
|
>>> parser.add_argument('-f')
|
||||||
>>> parser.parse_args(['-f', 'foo', '@args.txt'])
|
>>> parser.parse_args(['-f', 'foo', '@args.txt'])
|
||||||
|
@ -1109,9 +1109,9 @@ argument::
|
||||||
|
|
||||||
>>> parser = argparse.ArgumentParser(prog='frobble')
|
>>> parser = argparse.ArgumentParser(prog='frobble')
|
||||||
>>> parser.add_argument('--foo', action='store_true',
|
>>> parser.add_argument('--foo', action='store_true',
|
||||||
... help='foo the bars before frobbling')
|
... help='foo the bars before frobbling')
|
||||||
>>> parser.add_argument('bar', nargs='+',
|
>>> parser.add_argument('bar', nargs='+',
|
||||||
... help='one of the bars to be frobbled')
|
... help='one of the bars to be frobbled')
|
||||||
>>> parser.parse_args(['-h'])
|
>>> parser.parse_args(['-h'])
|
||||||
usage: frobble [-h] [--foo] bar [bar ...]
|
usage: frobble [-h] [--foo] bar [bar ...]
|
||||||
|
|
||||||
|
@ -1129,7 +1129,7 @@ specifiers include the program name, ``%(prog)s`` and most keyword arguments to
|
||||||
|
|
||||||
>>> parser = argparse.ArgumentParser(prog='frobble')
|
>>> parser = argparse.ArgumentParser(prog='frobble')
|
||||||
>>> parser.add_argument('bar', nargs='?', type=int, default=42,
|
>>> parser.add_argument('bar', nargs='?', type=int, default=42,
|
||||||
... help='the bar to %(prog)s (default: %(default)s)')
|
... help='the bar to %(prog)s (default: %(default)s)')
|
||||||
>>> parser.print_help()
|
>>> parser.print_help()
|
||||||
usage: frobble [-h] [bar]
|
usage: frobble [-h] [bar]
|
||||||
|
|
||||||
|
@ -1468,10 +1468,10 @@ interactive prompt::
|
||||||
>>> parser = argparse.ArgumentParser()
|
>>> parser = argparse.ArgumentParser()
|
||||||
>>> parser.add_argument(
|
>>> parser.add_argument(
|
||||||
... 'integers', metavar='int', type=int, choices=range(10),
|
... 'integers', metavar='int', type=int, choices=range(10),
|
||||||
... nargs='+', help='an integer in the range 0..9')
|
... nargs='+', help='an integer in the range 0..9')
|
||||||
>>> parser.add_argument(
|
>>> parser.add_argument(
|
||||||
... '--sum', dest='accumulate', action='store_const', const=sum,
|
... '--sum', dest='accumulate', action='store_const', const=sum,
|
||||||
... default=max, help='sum the integers (default: find the max)')
|
... default=max, help='sum the integers (default: find the max)')
|
||||||
>>> parser.parse_args(['1', '2', '3', '4'])
|
>>> parser.parse_args(['1', '2', '3', '4'])
|
||||||
Namespace(accumulate=<built-in function max>, integers=[1, 2, 3, 4])
|
Namespace(accumulate=<built-in function max>, integers=[1, 2, 3, 4])
|
||||||
>>> parser.parse_args(['1', '2', '3', '4', '--sum'])
|
>>> parser.parse_args(['1', '2', '3', '4', '--sum'])
|
||||||
|
|
|
@ -202,7 +202,7 @@ any extraneous data sent by the web client are ignored. ::
|
||||||
self.set_terminator(None)
|
self.set_terminator(None)
|
||||||
self.handle_request()
|
self.handle_request()
|
||||||
elif not self.handling:
|
elif not self.handling:
|
||||||
self.set_terminator(None) # browsers sometimes over-send
|
self.set_terminator(None) # browsers sometimes over-send
|
||||||
self.cgi_data = parse(self.headers, b"".join(self.ibuffer))
|
self.cgi_data = parse(self.headers, b"".join(self.ibuffer))
|
||||||
self.handling = True
|
self.handling = True
|
||||||
self.ibuffer = []
|
self.ibuffer = []
|
||||||
|
|
|
@ -71,14 +71,14 @@ Lock
|
||||||
lock = Lock()
|
lock = Lock()
|
||||||
...
|
...
|
||||||
with (yield from lock):
|
with (yield from lock):
|
||||||
...
|
...
|
||||||
|
|
||||||
Lock objects can be tested for locking state::
|
Lock objects can be tested for locking state::
|
||||||
|
|
||||||
if not lock.locked():
|
if not lock.locked():
|
||||||
yield from lock
|
yield from lock
|
||||||
else:
|
else:
|
||||||
# lock is acquired
|
# lock is acquired
|
||||||
...
|
...
|
||||||
|
|
||||||
.. method:: locked()
|
.. method:: locked()
|
||||||
|
|
|
@ -315,8 +315,8 @@ implement its socket handling::
|
||||||
self.buffer = self.buffer[sent:]
|
self.buffer = self.buffer[sent:]
|
||||||
|
|
||||||
|
|
||||||
client = HTTPClient('www.python.org', '/')
|
client = HTTPClient('www.python.org', '/')
|
||||||
asyncore.loop()
|
asyncore.loop()
|
||||||
|
|
||||||
.. _asyncore-example-2:
|
.. _asyncore-example-2:
|
||||||
|
|
||||||
|
|
|
@ -276,6 +276,6 @@ sample and subtract the whole output sample from the input sample::
|
||||||
# out_test)
|
# out_test)
|
||||||
prefill = '\0'*(pos+ipos)*2
|
prefill = '\0'*(pos+ipos)*2
|
||||||
postfill = '\0'*(len(inputdata)-len(prefill)-len(outputdata))
|
postfill = '\0'*(len(inputdata)-len(prefill)-len(outputdata))
|
||||||
outputdata = prefill + audioop.mul(outputdata,2,-factor) + postfill
|
outputdata = prefill + audioop.mul(outputdata, 2, -factor) + postfill
|
||||||
return audioop.add(inputdata, outputdata, 2)
|
return audioop.add(inputdata, outputdata, 2)
|
||||||
|
|
||||||
|
|
|
@ -218,19 +218,22 @@ The ABC supplies the remaining methods such as :meth:`__and__` and
|
||||||
:meth:`isdisjoint`::
|
:meth:`isdisjoint`::
|
||||||
|
|
||||||
class ListBasedSet(collections.abc.Set):
|
class ListBasedSet(collections.abc.Set):
|
||||||
''' Alternate set implementation favoring space over speed
|
''' Alternate set implementation favoring space over speed
|
||||||
and not requiring the set elements to be hashable. '''
|
and not requiring the set elements to be hashable. '''
|
||||||
def __init__(self, iterable):
|
def __init__(self, iterable):
|
||||||
self.elements = lst = []
|
self.elements = lst = []
|
||||||
for value in iterable:
|
for value in iterable:
|
||||||
if value not in lst:
|
if value not in lst:
|
||||||
lst.append(value)
|
lst.append(value)
|
||||||
def __iter__(self):
|
|
||||||
return iter(self.elements)
|
def __iter__(self):
|
||||||
def __contains__(self, value):
|
return iter(self.elements)
|
||||||
return value in self.elements
|
|
||||||
def __len__(self):
|
def __contains__(self, value):
|
||||||
return len(self.elements)
|
return value in self.elements
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.elements)
|
||||||
|
|
||||||
s1 = ListBasedSet('abcdef')
|
s1 = ListBasedSet('abcdef')
|
||||||
s2 = ListBasedSet('defghi')
|
s2 = ListBasedSet('defghi')
|
||||||
|
|
|
@ -1029,7 +1029,7 @@ Since an ordered dictionary remembers its insertion order, it can be used
|
||||||
in conjunction with sorting to make a sorted dictionary::
|
in conjunction with sorting to make a sorted dictionary::
|
||||||
|
|
||||||
>>> # regular unsorted dictionary
|
>>> # regular unsorted dictionary
|
||||||
>>> d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}
|
>>> d = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2}
|
||||||
|
|
||||||
>>> # dictionary sorted by key
|
>>> # dictionary sorted by key
|
||||||
>>> OrderedDict(sorted(d.items(), key=lambda t: t[0]))
|
>>> OrderedDict(sorted(d.items(), key=lambda t: t[0]))
|
||||||
|
|
|
@ -99,12 +99,12 @@ the results of another :class:`Future`. For example::
|
||||||
import time
|
import time
|
||||||
def wait_on_b():
|
def wait_on_b():
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
print(b.result()) # b will never complete because it is waiting on a.
|
print(b.result()) # b will never complete because it is waiting on a.
|
||||||
return 5
|
return 5
|
||||||
|
|
||||||
def wait_on_a():
|
def wait_on_a():
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
print(a.result()) # a will never complete because it is waiting on b.
|
print(a.result()) # a will never complete because it is waiting on b.
|
||||||
return 6
|
return 6
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -833,13 +833,13 @@ To get interpolation, use :class:`ConfigParser`::
|
||||||
|
|
||||||
# Set the optional *raw* argument of get() to True if you wish to disable
|
# Set the optional *raw* argument of get() to True if you wish to disable
|
||||||
# interpolation in a single get operation.
|
# interpolation in a single get operation.
|
||||||
print(cfg.get('Section1', 'foo', raw=False)) # -> "Python is fun!"
|
print(cfg.get('Section1', 'foo', raw=False)) # -> "Python is fun!"
|
||||||
print(cfg.get('Section1', 'foo', raw=True)) # -> "%(bar)s is %(baz)s!"
|
print(cfg.get('Section1', 'foo', raw=True)) # -> "%(bar)s is %(baz)s!"
|
||||||
|
|
||||||
# The optional *vars* argument is a dict with members that will take
|
# The optional *vars* argument is a dict with members that will take
|
||||||
# precedence in interpolation.
|
# precedence in interpolation.
|
||||||
print(cfg.get('Section1', 'foo', vars={'bar': 'Documentation',
|
print(cfg.get('Section1', 'foo', vars={'bar': 'Documentation',
|
||||||
'baz': 'evil'}))
|
'baz': 'evil'}))
|
||||||
|
|
||||||
# The optional *fallback* argument can be used to provide a fallback value
|
# The optional *fallback* argument can be used to provide a fallback value
|
||||||
print(cfg.get('Section1', 'foo'))
|
print(cfg.get('Section1', 'foo'))
|
||||||
|
@ -866,10 +866,10 @@ interpolation if an option used is not defined elsewhere. ::
|
||||||
config = configparser.ConfigParser({'bar': 'Life', 'baz': 'hard'})
|
config = configparser.ConfigParser({'bar': 'Life', 'baz': 'hard'})
|
||||||
config.read('example.cfg')
|
config.read('example.cfg')
|
||||||
|
|
||||||
print(config.get('Section1', 'foo')) # -> "Python is fun!"
|
print(config.get('Section1', 'foo')) # -> "Python is fun!"
|
||||||
config.remove_option('Section1', 'bar')
|
config.remove_option('Section1', 'bar')
|
||||||
config.remove_option('Section1', 'baz')
|
config.remove_option('Section1', 'baz')
|
||||||
print(config.get('Section1', 'foo')) # -> "Life is hard!"
|
print(config.get('Section1', 'foo')) # -> "Life is hard!"
|
||||||
|
|
||||||
|
|
||||||
.. _configparser-objects:
|
.. _configparser-objects:
|
||||||
|
|
|
@ -644,7 +644,7 @@ to yield if an attempt is made to use them a second time::
|
||||||
Before
|
Before
|
||||||
After
|
After
|
||||||
>>> with cm:
|
>>> with cm:
|
||||||
... pass
|
... pass
|
||||||
...
|
...
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
|
|
|
@ -149,4 +149,4 @@ check it against the original::
|
||||||
|
|
||||||
hashed = crypt.crypt(plaintext)
|
hashed = crypt.crypt(plaintext)
|
||||||
if not compare_hash(hashed, crypt.crypt(plaintext, hashed)):
|
if not compare_hash(hashed, crypt.crypt(plaintext, hashed)):
|
||||||
raise ValueError("hashed version doesn't validate against original")
|
raise ValueError("hashed version doesn't validate against original")
|
||||||
|
|
|
@ -52,11 +52,11 @@ library containing most standard C functions, and uses the cdecl calling
|
||||||
convention::
|
convention::
|
||||||
|
|
||||||
>>> from ctypes import *
|
>>> from ctypes import *
|
||||||
>>> print(windll.kernel32) # doctest: +WINDOWS
|
>>> print(windll.kernel32) # doctest: +WINDOWS
|
||||||
<WinDLL 'kernel32', handle ... at ...>
|
<WinDLL 'kernel32', handle ... at ...>
|
||||||
>>> print(cdll.msvcrt) # doctest: +WINDOWS
|
>>> print(cdll.msvcrt) # doctest: +WINDOWS
|
||||||
<CDLL 'msvcrt', handle ... at ...>
|
<CDLL 'msvcrt', handle ... at ...>
|
||||||
>>> libc = cdll.msvcrt # doctest: +WINDOWS
|
>>> libc = cdll.msvcrt # doctest: +WINDOWS
|
||||||
>>>
|
>>>
|
||||||
|
|
||||||
Windows appends the usual ``.dll`` file suffix automatically.
|
Windows appends the usual ``.dll`` file suffix automatically.
|
||||||
|
@ -72,10 +72,10 @@ load a library, so attribute access can not be used to load libraries. Either th
|
||||||
:meth:`LoadLibrary` method of the dll loaders should be used, or you should load
|
:meth:`LoadLibrary` method of the dll loaders should be used, or you should load
|
||||||
the library by creating an instance of CDLL by calling the constructor::
|
the library by creating an instance of CDLL by calling the constructor::
|
||||||
|
|
||||||
>>> cdll.LoadLibrary("libc.so.6") # doctest: +LINUX
|
>>> cdll.LoadLibrary("libc.so.6") # doctest: +LINUX
|
||||||
<CDLL 'libc.so.6', handle ... at ...>
|
<CDLL 'libc.so.6', handle ... at ...>
|
||||||
>>> libc = CDLL("libc.so.6") # doctest: +LINUX
|
>>> libc = CDLL("libc.so.6") # doctest: +LINUX
|
||||||
>>> libc # doctest: +LINUX
|
>>> libc # doctest: +LINUX
|
||||||
<CDLL 'libc.so.6', handle ... at ...>
|
<CDLL 'libc.so.6', handle ... at ...>
|
||||||
>>>
|
>>>
|
||||||
|
|
||||||
|
@ -92,9 +92,9 @@ Functions are accessed as attributes of dll objects::
|
||||||
>>> from ctypes import *
|
>>> from ctypes import *
|
||||||
>>> libc.printf
|
>>> libc.printf
|
||||||
<_FuncPtr object at 0x...>
|
<_FuncPtr object at 0x...>
|
||||||
>>> print(windll.kernel32.GetModuleHandleA) # doctest: +WINDOWS
|
>>> print(windll.kernel32.GetModuleHandleA) # doctest: +WINDOWS
|
||||||
<_FuncPtr object at 0x...>
|
<_FuncPtr object at 0x...>
|
||||||
>>> print(windll.kernel32.MyOwnFunction) # doctest: +WINDOWS
|
>>> print(windll.kernel32.MyOwnFunction) # doctest: +WINDOWS
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
File "<stdin>", line 1, in ?
|
File "<stdin>", line 1, in ?
|
||||||
File "ctypes.py", line 239, in __getattr__
|
File "ctypes.py", line 239, in __getattr__
|
||||||
|
@ -123,16 +123,16 @@ Sometimes, dlls export functions with names which aren't valid Python
|
||||||
identifiers, like ``"??2@YAPAXI@Z"``. In this case you have to use
|
identifiers, like ``"??2@YAPAXI@Z"``. In this case you have to use
|
||||||
:func:`getattr` to retrieve the function::
|
:func:`getattr` to retrieve the function::
|
||||||
|
|
||||||
>>> getattr(cdll.msvcrt, "??2@YAPAXI@Z") # doctest: +WINDOWS
|
>>> getattr(cdll.msvcrt, "??2@YAPAXI@Z") # doctest: +WINDOWS
|
||||||
<_FuncPtr object at 0x...>
|
<_FuncPtr object at 0x...>
|
||||||
>>>
|
>>>
|
||||||
|
|
||||||
On Windows, some dlls export functions not by name but by ordinal. These
|
On Windows, some dlls export functions not by name but by ordinal. These
|
||||||
functions can be accessed by indexing the dll object with the ordinal number::
|
functions can be accessed by indexing the dll object with the ordinal number::
|
||||||
|
|
||||||
>>> cdll.kernel32[1] # doctest: +WINDOWS
|
>>> cdll.kernel32[1] # doctest: +WINDOWS
|
||||||
<_FuncPtr object at 0x...>
|
<_FuncPtr object at 0x...>
|
||||||
>>> cdll.kernel32[0] # doctest: +WINDOWS
|
>>> cdll.kernel32[0] # doctest: +WINDOWS
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
File "<stdin>", line 1, in ?
|
File "<stdin>", line 1, in ?
|
||||||
File "ctypes.py", line 310, in __getitem__
|
File "ctypes.py", line 310, in __getitem__
|
||||||
|
@ -154,9 +154,9 @@ handle.
|
||||||
This example calls both functions with a NULL pointer (``None`` should be used
|
This example calls both functions with a NULL pointer (``None`` should be used
|
||||||
as the NULL pointer)::
|
as the NULL pointer)::
|
||||||
|
|
||||||
>>> print(libc.time(None)) # doctest: +SKIP
|
>>> print(libc.time(None)) # doctest: +SKIP
|
||||||
1150640792
|
1150640792
|
||||||
>>> print(hex(windll.kernel32.GetModuleHandleA(None))) # doctest: +WINDOWS
|
>>> print(hex(windll.kernel32.GetModuleHandleA(None))) # doctest: +WINDOWS
|
||||||
0x1d000000
|
0x1d000000
|
||||||
>>>
|
>>>
|
||||||
|
|
||||||
|
@ -165,11 +165,11 @@ of arguments or the wrong calling convention. Unfortunately this only works on
|
||||||
Windows. It does this by examining the stack after the function returns, so
|
Windows. It does this by examining the stack after the function returns, so
|
||||||
although an error is raised the function *has* been called::
|
although an error is raised the function *has* been called::
|
||||||
|
|
||||||
>>> windll.kernel32.GetModuleHandleA() # doctest: +WINDOWS
|
>>> windll.kernel32.GetModuleHandleA() # doctest: +WINDOWS
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
File "<stdin>", line 1, in ?
|
File "<stdin>", line 1, in ?
|
||||||
ValueError: Procedure probably called with not enough arguments (4 bytes missing)
|
ValueError: Procedure probably called with not enough arguments (4 bytes missing)
|
||||||
>>> windll.kernel32.GetModuleHandleA(0, 0) # doctest: +WINDOWS
|
>>> windll.kernel32.GetModuleHandleA(0, 0) # doctest: +WINDOWS
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
File "<stdin>", line 1, in ?
|
File "<stdin>", line 1, in ?
|
||||||
ValueError: Procedure probably called with too many arguments (4 bytes in excess)
|
ValueError: Procedure probably called with too many arguments (4 bytes in excess)
|
||||||
|
@ -178,13 +178,13 @@ although an error is raised the function *has* been called::
|
||||||
The same exception is raised when you call an ``stdcall`` function with the
|
The same exception is raised when you call an ``stdcall`` function with the
|
||||||
``cdecl`` calling convention, or vice versa::
|
``cdecl`` calling convention, or vice versa::
|
||||||
|
|
||||||
>>> cdll.kernel32.GetModuleHandleA(None) # doctest: +WINDOWS
|
>>> cdll.kernel32.GetModuleHandleA(None) # doctest: +WINDOWS
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
File "<stdin>", line 1, in ?
|
File "<stdin>", line 1, in ?
|
||||||
ValueError: Procedure probably called with not enough arguments (4 bytes missing)
|
ValueError: Procedure probably called with not enough arguments (4 bytes missing)
|
||||||
>>>
|
>>>
|
||||||
|
|
||||||
>>> windll.msvcrt.printf(b"spam") # doctest: +WINDOWS
|
>>> windll.msvcrt.printf(b"spam") # doctest: +WINDOWS
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
File "<stdin>", line 1, in ?
|
File "<stdin>", line 1, in ?
|
||||||
ValueError: Procedure probably called with too many arguments (4 bytes in excess)
|
ValueError: Procedure probably called with too many arguments (4 bytes in excess)
|
||||||
|
@ -197,7 +197,7 @@ On Windows, :mod:`ctypes` uses win32 structured exception handling to prevent
|
||||||
crashes from general protection faults when functions are called with invalid
|
crashes from general protection faults when functions are called with invalid
|
||||||
argument values::
|
argument values::
|
||||||
|
|
||||||
>>> windll.kernel32.GetModuleHandleA(32) # doctest: +WINDOWS
|
>>> windll.kernel32.GetModuleHandleA(32) # doctest: +WINDOWS
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
File "<stdin>", line 1, in ?
|
File "<stdin>", line 1, in ?
|
||||||
OSError: exception: access violation reading 0x00000020
|
OSError: exception: access violation reading 0x00000020
|
||||||
|
@ -462,9 +462,9 @@ Here is a more advanced example, it uses the ``strchr`` function, which expects
|
||||||
a string pointer and a char, and returns a pointer to a string::
|
a string pointer and a char, and returns a pointer to a string::
|
||||||
|
|
||||||
>>> strchr = libc.strchr
|
>>> strchr = libc.strchr
|
||||||
>>> strchr(b"abcdef", ord("d")) # doctest: +SKIP
|
>>> strchr(b"abcdef", ord("d")) # doctest: +SKIP
|
||||||
8059983
|
8059983
|
||||||
>>> strchr.restype = c_char_p # c_char_p is a pointer to a string
|
>>> strchr.restype = c_char_p # c_char_p is a pointer to a string
|
||||||
>>> strchr(b"abcdef", ord("d"))
|
>>> strchr(b"abcdef", ord("d"))
|
||||||
b'def'
|
b'def'
|
||||||
>>> print(strchr(b"abcdef", ord("x")))
|
>>> print(strchr(b"abcdef", ord("x")))
|
||||||
|
@ -495,17 +495,17 @@ callable will be called with the *integer* the C function returns, and the
|
||||||
result of this call will be used as the result of your function call. This is
|
result of this call will be used as the result of your function call. This is
|
||||||
useful to check for error return values and automatically raise an exception::
|
useful to check for error return values and automatically raise an exception::
|
||||||
|
|
||||||
>>> GetModuleHandle = windll.kernel32.GetModuleHandleA # doctest: +WINDOWS
|
>>> GetModuleHandle = windll.kernel32.GetModuleHandleA # doctest: +WINDOWS
|
||||||
>>> def ValidHandle(value):
|
>>> def ValidHandle(value):
|
||||||
... if value == 0:
|
... if value == 0:
|
||||||
... raise WinError()
|
... raise WinError()
|
||||||
... return value
|
... return value
|
||||||
...
|
...
|
||||||
>>>
|
>>>
|
||||||
>>> GetModuleHandle.restype = ValidHandle # doctest: +WINDOWS
|
>>> GetModuleHandle.restype = ValidHandle # doctest: +WINDOWS
|
||||||
>>> GetModuleHandle(None) # doctest: +WINDOWS
|
>>> GetModuleHandle(None) # doctest: +WINDOWS
|
||||||
486539264
|
486539264
|
||||||
>>> GetModuleHandle("something silly") # doctest: +WINDOWS
|
>>> GetModuleHandle("something silly") # doctest: +WINDOWS
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
File "<stdin>", line 1, in ?
|
File "<stdin>", line 1, in ?
|
||||||
File "<stdin>", line 3, in ValidHandle
|
File "<stdin>", line 3, in ValidHandle
|
||||||
|
@ -676,12 +676,12 @@ POINTs among other stuff::
|
||||||
|
|
||||||
>>> from ctypes import *
|
>>> from ctypes import *
|
||||||
>>> class POINT(Structure):
|
>>> class POINT(Structure):
|
||||||
... _fields_ = ("x", c_int), ("y", c_int)
|
... _fields_ = ("x", c_int), ("y", c_int)
|
||||||
...
|
...
|
||||||
>>> class MyStruct(Structure):
|
>>> class MyStruct(Structure):
|
||||||
... _fields_ = [("a", c_int),
|
... _fields_ = [("a", c_int),
|
||||||
... ("b", c_float),
|
... ("b", c_float),
|
||||||
... ("point_array", POINT * 4)]
|
... ("point_array", POINT * 4)]
|
||||||
>>>
|
>>>
|
||||||
>>> print(len(MyStruct().point_array))
|
>>> print(len(MyStruct().point_array))
|
||||||
4
|
4
|
||||||
|
@ -998,7 +998,7 @@ passed::
|
||||||
|
|
||||||
The result::
|
The result::
|
||||||
|
|
||||||
>>> qsort(ia, len(ia), sizeof(c_int), cmp_func) # doctest: +LINUX
|
>>> qsort(ia, len(ia), sizeof(c_int), cmp_func) # doctest: +LINUX
|
||||||
py_cmp_func 5 1
|
py_cmp_func 5 1
|
||||||
py_cmp_func 33 99
|
py_cmp_func 33 99
|
||||||
py_cmp_func 7 33
|
py_cmp_func 7 33
|
||||||
|
@ -1100,9 +1100,9 @@ access violation or whatever, so it's better to break out of the loop when we
|
||||||
hit the NULL entry::
|
hit the NULL entry::
|
||||||
|
|
||||||
>>> for item in table:
|
>>> for item in table:
|
||||||
... print(item.name, item.size)
|
... print(item.name, item.size)
|
||||||
... if item.name is None:
|
... if item.name is None:
|
||||||
... break
|
... break
|
||||||
...
|
...
|
||||||
__hello__ 104
|
__hello__ 104
|
||||||
__phello__ -104
|
__phello__ -104
|
||||||
|
|
|
@ -171,7 +171,7 @@ headers.
|
||||||
:class:`~datetime.datetime` instance. This means, for example, that
|
:class:`~datetime.datetime` instance. This means, for example, that
|
||||||
the following code is valid and does what one would expect::
|
the following code is valid and does what one would expect::
|
||||||
|
|
||||||
msg['Date'] = datetime(2011, 7, 15, 21)
|
msg['Date'] = datetime(2011, 7, 15, 21)
|
||||||
|
|
||||||
Because this is a naive ``datetime`` it will be interpreted as a UTC
|
Because this is a naive ``datetime`` it will be interpreted as a UTC
|
||||||
timestamp, and the resulting value will have a timezone of ``-0000``. Much
|
timestamp, and the resulting value will have a timezone of ``-0000``. Much
|
||||||
|
|
|
@ -124,7 +124,7 @@ In a script, typical usage is something like this::
|
||||||
opts, args = getopt.getopt(sys.argv[1:], "ho:v", ["help", "output="])
|
opts, args = getopt.getopt(sys.argv[1:], "ho:v", ["help", "output="])
|
||||||
except getopt.GetoptError as err:
|
except getopt.GetoptError as err:
|
||||||
# print help information and exit:
|
# print help information and exit:
|
||||||
print(err) # will print something like "option -a not recognized"
|
print(err) # will print something like "option -a not recognized"
|
||||||
usage()
|
usage()
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
output = None
|
output = None
|
||||||
|
|
|
@ -51,8 +51,10 @@ as they are encountered::
|
||||||
class MyHTMLParser(HTMLParser):
|
class MyHTMLParser(HTMLParser):
|
||||||
def handle_starttag(self, tag, attrs):
|
def handle_starttag(self, tag, attrs):
|
||||||
print("Encountered a start tag:", tag)
|
print("Encountered a start tag:", tag)
|
||||||
|
|
||||||
def handle_endtag(self, tag):
|
def handle_endtag(self, tag):
|
||||||
print("Encountered an end tag :", tag)
|
print("Encountered an end tag :", tag)
|
||||||
|
|
||||||
def handle_data(self, data):
|
def handle_data(self, data):
|
||||||
print("Encountered some data :", data)
|
print("Encountered some data :", data)
|
||||||
|
|
||||||
|
@ -237,21 +239,27 @@ examples::
|
||||||
print("Start tag:", tag)
|
print("Start tag:", tag)
|
||||||
for attr in attrs:
|
for attr in attrs:
|
||||||
print(" attr:", attr)
|
print(" attr:", attr)
|
||||||
|
|
||||||
def handle_endtag(self, tag):
|
def handle_endtag(self, tag):
|
||||||
print("End tag :", tag)
|
print("End tag :", tag)
|
||||||
|
|
||||||
def handle_data(self, data):
|
def handle_data(self, data):
|
||||||
print("Data :", data)
|
print("Data :", data)
|
||||||
|
|
||||||
def handle_comment(self, data):
|
def handle_comment(self, data):
|
||||||
print("Comment :", data)
|
print("Comment :", data)
|
||||||
|
|
||||||
def handle_entityref(self, name):
|
def handle_entityref(self, name):
|
||||||
c = chr(name2codepoint[name])
|
c = chr(name2codepoint[name])
|
||||||
print("Named ent:", c)
|
print("Named ent:", c)
|
||||||
|
|
||||||
def handle_charref(self, name):
|
def handle_charref(self, name):
|
||||||
if name.startswith('x'):
|
if name.startswith('x'):
|
||||||
c = chr(int(name[1:], 16))
|
c = chr(int(name[1:], 16))
|
||||||
else:
|
else:
|
||||||
c = chr(int(name))
|
c = chr(int(name))
|
||||||
print("Num ent :", c)
|
print("Num ent :", c)
|
||||||
|
|
||||||
def handle_decl(self, data):
|
def handle_decl(self, data):
|
||||||
print("Decl :", data)
|
print("Decl :", data)
|
||||||
|
|
||||||
|
@ -283,7 +291,7 @@ further parsing::
|
||||||
attr: ('type', 'text/css')
|
attr: ('type', 'text/css')
|
||||||
Data : #python { color: green }
|
Data : #python { color: green }
|
||||||
End tag : style
|
End tag : style
|
||||||
>>>
|
|
||||||
>>> parser.feed('<script type="text/javascript">'
|
>>> parser.feed('<script type="text/javascript">'
|
||||||
... 'alert("<strong>hello!</strong>");</script>')
|
... 'alert("<strong>hello!</strong>");</script>')
|
||||||
Start tag: script
|
Start tag: script
|
||||||
|
|
|
@ -441,7 +441,7 @@ Here is an example session that uses the ``GET`` method::
|
||||||
>>> conn.request("GET", "/")
|
>>> conn.request("GET", "/")
|
||||||
>>> r1 = conn.getresponse()
|
>>> r1 = conn.getresponse()
|
||||||
>>> while not r1.closed:
|
>>> while not r1.closed:
|
||||||
... print(r1.read(200)) # 200 bytes
|
... print(r1.read(200)) # 200 bytes
|
||||||
b'<!doctype html>\n<!--[if"...
|
b'<!doctype html>\n<!--[if"...
|
||||||
...
|
...
|
||||||
>>> # Example of an invalid request
|
>>> # Example of an invalid request
|
||||||
|
|
|
@ -787,7 +787,7 @@ function.
|
||||||
functions::
|
functions::
|
||||||
|
|
||||||
def test(a, *, b):
|
def test(a, *, b):
|
||||||
...
|
...
|
||||||
|
|
||||||
sig = signature(test)
|
sig = signature(test)
|
||||||
ba = sig.bind(10, b=20)
|
ba = sig.bind(10, b=20)
|
||||||
|
|
|
@ -653,7 +653,7 @@ network. For iteration, *all* hosts are returned, including unusable hosts
|
||||||
example::
|
example::
|
||||||
|
|
||||||
>>> for addr in IPv4Network('192.0.2.0/28'):
|
>>> for addr in IPv4Network('192.0.2.0/28'):
|
||||||
... addr
|
... addr
|
||||||
...
|
...
|
||||||
IPv4Address('192.0.2.0')
|
IPv4Address('192.0.2.0')
|
||||||
IPv4Address('192.0.2.1')
|
IPv4Address('192.0.2.1')
|
||||||
|
|
|
@ -467,13 +467,13 @@ The :mod:`locale` module defines the following exception and functions:
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
>>> import locale
|
>>> import locale
|
||||||
>>> loc = locale.getlocale() # get current locale
|
>>> loc = locale.getlocale() # get current locale
|
||||||
# use German locale; name might vary with platform
|
# use German locale; name might vary with platform
|
||||||
>>> locale.setlocale(locale.LC_ALL, 'de_DE')
|
>>> locale.setlocale(locale.LC_ALL, 'de_DE')
|
||||||
>>> locale.strcoll('f\xe4n', 'foo') # compare a string containing an umlaut
|
>>> locale.strcoll('f\xe4n', 'foo') # compare a string containing an umlaut
|
||||||
>>> locale.setlocale(locale.LC_ALL, '') # use user's preferred locale
|
>>> locale.setlocale(locale.LC_ALL, '') # use user's preferred locale
|
||||||
>>> locale.setlocale(locale.LC_ALL, 'C') # use default (C) locale
|
>>> locale.setlocale(locale.LC_ALL, 'C') # use default (C) locale
|
||||||
>>> locale.setlocale(locale.LC_ALL, loc) # restore saved locale
|
>>> locale.setlocale(locale.LC_ALL, loc) # restore saved locale
|
||||||
|
|
||||||
|
|
||||||
Background, details, hints, tips and caveats
|
Background, details, hints, tips and caveats
|
||||||
|
|
|
@ -70,7 +70,7 @@ standard. However, mailcap files are supported on most Unix systems.
|
||||||
An example usage::
|
An example usage::
|
||||||
|
|
||||||
>>> import mailcap
|
>>> import mailcap
|
||||||
>>> d=mailcap.getcaps()
|
>>> d = mailcap.getcaps()
|
||||||
>>> mailcap.findmatch(d, 'video/mpeg', filename='tmp1223')
|
>>> mailcap.findmatch(d, 'video/mpeg', filename='tmp1223')
|
||||||
('xmpeg tmp1223', {'view': 'xmpeg %s'})
|
('xmpeg tmp1223', {'view': 'xmpeg %s'})
|
||||||
|
|
||||||
|
|
|
@ -144,7 +144,7 @@ To map anonymous memory, -1 should be passed as the fileno along with the length
|
||||||
|
|
||||||
pid = os.fork()
|
pid = os.fork()
|
||||||
|
|
||||||
if pid == 0: # In a child process
|
if pid == 0: # In a child process
|
||||||
mm.seek(0)
|
mm.seek(0)
|
||||||
print(mm.readline())
|
print(mm.readline())
|
||||||
|
|
||||||
|
|
|
@ -2663,8 +2663,8 @@ Explicitly pass resources to child processes
|
||||||
... do something using "lock" ...
|
... do something using "lock" ...
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
lock = Lock()
|
lock = Lock()
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
Process(target=f).start()
|
Process(target=f).start()
|
||||||
|
|
||||||
should be rewritten as ::
|
should be rewritten as ::
|
||||||
|
@ -2675,8 +2675,8 @@ Explicitly pass resources to child processes
|
||||||
... do something using "l" ...
|
... do something using "l" ...
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
lock = Lock()
|
lock = Lock()
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
Process(target=f, args=(lock,)).start()
|
Process(target=f, args=(lock,)).start()
|
||||||
|
|
||||||
Beware of replacing :data:`sys.stdin` with a "file like object"
|
Beware of replacing :data:`sys.stdin` with a "file like object"
|
||||||
|
|
|
@ -25,7 +25,7 @@ GNU/POSIX syntax, and additionally generates usage and help messages for you.
|
||||||
Here's an example of using :mod:`optparse` in a simple script::
|
Here's an example of using :mod:`optparse` in a simple script::
|
||||||
|
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
[...]
|
...
|
||||||
parser = OptionParser()
|
parser = OptionParser()
|
||||||
parser.add_option("-f", "--file", dest="filename",
|
parser.add_option("-f", "--file", dest="filename",
|
||||||
help="write report to FILE", metavar="FILE")
|
help="write report to FILE", metavar="FILE")
|
||||||
|
@ -252,7 +252,7 @@ First, you need to import the OptionParser class; then, early in the main
|
||||||
program, create an OptionParser instance::
|
program, create an OptionParser instance::
|
||||||
|
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
[...]
|
...
|
||||||
parser = OptionParser()
|
parser = OptionParser()
|
||||||
|
|
||||||
Then you can start defining options. The basic syntax is::
|
Then you can start defining options. The basic syntax is::
|
||||||
|
@ -718,7 +718,7 @@ you can call :func:`OptionParser.error` to signal an application-defined error
|
||||||
condition::
|
condition::
|
||||||
|
|
||||||
(options, args) = parser.parse_args()
|
(options, args) = parser.parse_args()
|
||||||
[...]
|
...
|
||||||
if options.a and options.b:
|
if options.a and options.b:
|
||||||
parser.error("options -a and -b are mutually exclusive")
|
parser.error("options -a and -b are mutually exclusive")
|
||||||
|
|
||||||
|
@ -758,7 +758,7 @@ Putting it all together
|
||||||
Here's what :mod:`optparse`\ -based scripts usually look like::
|
Here's what :mod:`optparse`\ -based scripts usually look like::
|
||||||
|
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
[...]
|
...
|
||||||
def main():
|
def main():
|
||||||
usage = "usage: %prog [options] arg"
|
usage = "usage: %prog [options] arg"
|
||||||
parser = OptionParser(usage)
|
parser = OptionParser(usage)
|
||||||
|
@ -768,13 +768,13 @@ Here's what :mod:`optparse`\ -based scripts usually look like::
|
||||||
action="store_true", dest="verbose")
|
action="store_true", dest="verbose")
|
||||||
parser.add_option("-q", "--quiet",
|
parser.add_option("-q", "--quiet",
|
||||||
action="store_false", dest="verbose")
|
action="store_false", dest="verbose")
|
||||||
[...]
|
...
|
||||||
(options, args) = parser.parse_args()
|
(options, args) = parser.parse_args()
|
||||||
if len(args) != 1:
|
if len(args) != 1:
|
||||||
parser.error("incorrect number of arguments")
|
parser.error("incorrect number of arguments")
|
||||||
if options.verbose:
|
if options.verbose:
|
||||||
print("reading %s..." % options.filename)
|
print("reading %s..." % options.filename)
|
||||||
[...]
|
...
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
@ -1409,7 +1409,7 @@ If you're not careful, it's easy to define options with conflicting option
|
||||||
strings::
|
strings::
|
||||||
|
|
||||||
parser.add_option("-n", "--dry-run", ...)
|
parser.add_option("-n", "--dry-run", ...)
|
||||||
[...]
|
...
|
||||||
parser.add_option("-n", "--noisy", ...)
|
parser.add_option("-n", "--noisy", ...)
|
||||||
|
|
||||||
(This is particularly true if you've defined your own OptionParser subclass with
|
(This is particularly true if you've defined your own OptionParser subclass with
|
||||||
|
@ -1450,7 +1450,7 @@ that option. If the user asks for help, the help message will reflect that::
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--dry-run do no harm
|
--dry-run do no harm
|
||||||
[...]
|
...
|
||||||
-n, --noisy be noisy
|
-n, --noisy be noisy
|
||||||
|
|
||||||
It's possible to whittle away the option strings for a previously-added option
|
It's possible to whittle away the option strings for a previously-added option
|
||||||
|
@ -1465,7 +1465,7 @@ At this point, the original ``-n``/``--dry-run`` option is no longer
|
||||||
accessible, so :mod:`optparse` removes it, leaving this help text::
|
accessible, so :mod:`optparse` removes it, leaving this help text::
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
[...]
|
...
|
||||||
-n, --noisy be noisy
|
-n, --noisy be noisy
|
||||||
--dry-run new dry-run option
|
--dry-run new dry-run option
|
||||||
|
|
||||||
|
@ -1701,7 +1701,7 @@ seen, but blow up if it comes after ``-b`` in the command-line. ::
|
||||||
if parser.values.b:
|
if parser.values.b:
|
||||||
raise OptionValueError("can't use -a after -b")
|
raise OptionValueError("can't use -a after -b")
|
||||||
parser.values.a = 1
|
parser.values.a = 1
|
||||||
[...]
|
...
|
||||||
parser.add_option("-a", action="callback", callback=check_order)
|
parser.add_option("-a", action="callback", callback=check_order)
|
||||||
parser.add_option("-b", action="store_true", dest="b")
|
parser.add_option("-b", action="store_true", dest="b")
|
||||||
|
|
||||||
|
@ -1719,7 +1719,7 @@ message and the flag that it sets must be generalized. ::
|
||||||
if parser.values.b:
|
if parser.values.b:
|
||||||
raise OptionValueError("can't use %s after -b" % opt_str)
|
raise OptionValueError("can't use %s after -b" % opt_str)
|
||||||
setattr(parser.values, option.dest, 1)
|
setattr(parser.values, option.dest, 1)
|
||||||
[...]
|
...
|
||||||
parser.add_option("-a", action="callback", callback=check_order, dest='a')
|
parser.add_option("-a", action="callback", callback=check_order, dest='a')
|
||||||
parser.add_option("-b", action="store_true", dest="b")
|
parser.add_option("-b", action="store_true", dest="b")
|
||||||
parser.add_option("-c", action="callback", callback=check_order, dest='c')
|
parser.add_option("-c", action="callback", callback=check_order, dest='c')
|
||||||
|
@ -1739,7 +1739,7 @@ should not be called when the moon is full, all you have to do is this::
|
||||||
raise OptionValueError("%s option invalid when moon is full"
|
raise OptionValueError("%s option invalid when moon is full"
|
||||||
% opt_str)
|
% opt_str)
|
||||||
setattr(parser.values, option.dest, 1)
|
setattr(parser.values, option.dest, 1)
|
||||||
[...]
|
...
|
||||||
parser.add_option("--foo",
|
parser.add_option("--foo",
|
||||||
action="callback", callback=check_moon, dest="foo")
|
action="callback", callback=check_moon, dest="foo")
|
||||||
|
|
||||||
|
@ -1762,7 +1762,7 @@ Here's an example that just emulates the standard ``"store"`` action::
|
||||||
|
|
||||||
def store_value(option, opt_str, value, parser):
|
def store_value(option, opt_str, value, parser):
|
||||||
setattr(parser.values, option.dest, value)
|
setattr(parser.values, option.dest, value)
|
||||||
[...]
|
...
|
||||||
parser.add_option("--foo",
|
parser.add_option("--foo",
|
||||||
action="callback", callback=store_value,
|
action="callback", callback=store_value,
|
||||||
type="int", nargs=3, dest="foo")
|
type="int", nargs=3, dest="foo")
|
||||||
|
@ -1824,9 +1824,9 @@ arguments::
|
||||||
del parser.rargs[:len(value)]
|
del parser.rargs[:len(value)]
|
||||||
setattr(parser.values, option.dest, value)
|
setattr(parser.values, option.dest, value)
|
||||||
|
|
||||||
[...]
|
...
|
||||||
parser.add_option("-c", "--callback", dest="vararg_attr",
|
parser.add_option("-c", "--callback", dest="vararg_attr",
|
||||||
action="callback", callback=vararg_callback)
|
action="callback", callback=vararg_callback)
|
||||||
|
|
||||||
|
|
||||||
.. _optparse-extending-optparse:
|
.. _optparse-extending-optparse:
|
||||||
|
|
|
@ -1234,15 +1234,15 @@ does by default).
|
||||||
|
|
||||||
For example::
|
For example::
|
||||||
|
|
||||||
>>> re.match("c", "abcdef") # No match
|
>>> re.match("c", "abcdef") # No match
|
||||||
>>> re.search("c", "abcdef") # Match
|
>>> re.search("c", "abcdef") # Match
|
||||||
<_sre.SRE_Match object; span=(2, 3), match='c'>
|
<_sre.SRE_Match object; span=(2, 3), match='c'>
|
||||||
|
|
||||||
Regular expressions beginning with ``'^'`` can be used with :func:`search` to
|
Regular expressions beginning with ``'^'`` can be used with :func:`search` to
|
||||||
restrict the match at the beginning of the string::
|
restrict the match at the beginning of the string::
|
||||||
|
|
||||||
>>> re.match("c", "abcdef") # No match
|
>>> re.match("c", "abcdef") # No match
|
||||||
>>> re.search("^c", "abcdef") # No match
|
>>> re.search("^c", "abcdef") # No match
|
||||||
>>> re.search("^a", "abcdef") # Match
|
>>> re.search("^a", "abcdef") # Match
|
||||||
<_sre.SRE_Match object; span=(0, 1), match='a'>
|
<_sre.SRE_Match object; span=(0, 1), match='a'>
|
||||||
|
|
||||||
|
@ -1323,9 +1323,9 @@ a function to "munge" text, or randomize the order of all the characters
|
||||||
in each word of a sentence except for the first and last characters::
|
in each word of a sentence except for the first and last characters::
|
||||||
|
|
||||||
>>> def repl(m):
|
>>> def repl(m):
|
||||||
... inner_word = list(m.group(2))
|
... inner_word = list(m.group(2))
|
||||||
... random.shuffle(inner_word)
|
... random.shuffle(inner_word)
|
||||||
... return m.group(1) + "".join(inner_word) + m.group(3)
|
... return m.group(1) + "".join(inner_word) + m.group(3)
|
||||||
>>> text = "Professor Abdolmalek, please report your absences promptly."
|
>>> text = "Professor Abdolmalek, please report your absences promptly."
|
||||||
>>> re.sub(r"(\w)(\w+)(\w)", repl, text)
|
>>> re.sub(r"(\w)(\w+)(\w)", repl, text)
|
||||||
'Poefsrosr Aealmlobdk, pslaee reorpt your abnseces plmrptoy.'
|
'Poefsrosr Aealmlobdk, pslaee reorpt your abnseces plmrptoy.'
|
||||||
|
@ -1405,14 +1405,14 @@ successive matches::
|
||||||
def tokenize(code):
|
def tokenize(code):
|
||||||
keywords = {'IF', 'THEN', 'ENDIF', 'FOR', 'NEXT', 'GOSUB', 'RETURN'}
|
keywords = {'IF', 'THEN', 'ENDIF', 'FOR', 'NEXT', 'GOSUB', 'RETURN'}
|
||||||
token_specification = [
|
token_specification = [
|
||||||
('NUMBER', r'\d+(\.\d*)?'), # Integer or decimal number
|
('NUMBER', r'\d+(\.\d*)?'), # Integer or decimal number
|
||||||
('ASSIGN', r':='), # Assignment operator
|
('ASSIGN', r':='), # Assignment operator
|
||||||
('END', r';'), # Statement terminator
|
('END', r';'), # Statement terminator
|
||||||
('ID', r'[A-Za-z]+'), # Identifiers
|
('ID', r'[A-Za-z]+'), # Identifiers
|
||||||
('OP', r'[+\-*/]'), # Arithmetic operators
|
('OP', r'[+\-*/]'), # Arithmetic operators
|
||||||
('NEWLINE', r'\n'), # Line endings
|
('NEWLINE', r'\n'), # Line endings
|
||||||
('SKIP', r'[ \t]+'), # Skip over spaces and tabs
|
('SKIP', r'[ \t]+'), # Skip over spaces and tabs
|
||||||
('MISMATCH',r'.'), # Any other character
|
('MISMATCH',r'.'), # Any other character
|
||||||
]
|
]
|
||||||
tok_regex = '|'.join('(?P<%s>%s)' % pair for pair in token_specification)
|
tok_regex = '|'.join('(?P<%s>%s)' % pair for pair in token_specification)
|
||||||
line_num = 1
|
line_num = 1
|
||||||
|
|
|
@ -165,32 +165,33 @@ object)::
|
||||||
|
|
||||||
import shelve
|
import shelve
|
||||||
|
|
||||||
d = shelve.open(filename) # open -- file may get suffix added by low-level
|
d = shelve.open(filename) # open -- file may get suffix added by low-level
|
||||||
# library
|
# library
|
||||||
|
|
||||||
d[key] = data # store data at key (overwrites old data if
|
d[key] = data # store data at key (overwrites old data if
|
||||||
# using an existing key)
|
# using an existing key)
|
||||||
data = d[key] # retrieve a COPY of data at key (raise KeyError if no
|
data = d[key] # retrieve a COPY of data at key (raise KeyError
|
||||||
# such key)
|
# if no such key)
|
||||||
del d[key] # delete data stored at key (raises KeyError
|
del d[key] # delete data stored at key (raises KeyError
|
||||||
# if no such key)
|
# if no such key)
|
||||||
flag = key in d # true if the key exists
|
|
||||||
klist = list(d.keys()) # a list of all existing keys (slow!)
|
flag = key in d # true if the key exists
|
||||||
|
klist = list(d.keys()) # a list of all existing keys (slow!)
|
||||||
|
|
||||||
# as d was opened WITHOUT writeback=True, beware:
|
# as d was opened WITHOUT writeback=True, beware:
|
||||||
d['xx'] = [0, 1, 2] # this works as expected, but...
|
d['xx'] = [0, 1, 2] # this works as expected, but...
|
||||||
d['xx'].append(3) # *this doesn't!* -- d['xx'] is STILL [0, 1, 2]!
|
d['xx'].append(3) # *this doesn't!* -- d['xx'] is STILL [0, 1, 2]!
|
||||||
|
|
||||||
# having opened d without writeback=True, you need to code carefully:
|
# having opened d without writeback=True, you need to code carefully:
|
||||||
temp = d['xx'] # extracts the copy
|
temp = d['xx'] # extracts the copy
|
||||||
temp.append(5) # mutates the copy
|
temp.append(5) # mutates the copy
|
||||||
d['xx'] = temp # stores the copy right back, to persist it
|
d['xx'] = temp # stores the copy right back, to persist it
|
||||||
|
|
||||||
# or, d=shelve.open(filename,writeback=True) would let you just code
|
# or, d=shelve.open(filename,writeback=True) would let you just code
|
||||||
# d['xx'].append(5) and have it work as expected, BUT it would also
|
# d['xx'].append(5) and have it work as expected, BUT it would also
|
||||||
# consume more memory and make the d.close() operation slower.
|
# consume more memory and make the d.close() operation slower.
|
||||||
|
|
||||||
d.close() # close it
|
d.close() # close it
|
||||||
|
|
||||||
|
|
||||||
.. seealso::
|
.. seealso::
|
||||||
|
|
|
@ -1585,7 +1585,7 @@ should use the following idiom::
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
... # do something that requires SSL support
|
... # do something that requires SSL support
|
||||||
|
|
||||||
Client-side operation
|
Client-side operation
|
||||||
^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
@ -234,12 +234,12 @@ does an index lookup using :func:`__getitem__`.
|
||||||
|
|
||||||
Some simple format string examples::
|
Some simple format string examples::
|
||||||
|
|
||||||
"First, thou shalt count to {0}" # References first positional argument
|
"First, thou shalt count to {0}" # References first positional argument
|
||||||
"Bring me a {}" # Implicitly references the first positional argument
|
"Bring me a {}" # Implicitly references the first positional argument
|
||||||
"From {} to {}" # Same as "From {0} to {1}"
|
"From {} to {}" # Same as "From {0} to {1}"
|
||||||
"My quest is {name}" # References keyword argument 'name'
|
"My quest is {name}" # References keyword argument 'name'
|
||||||
"Weight in tons {0.weight}" # 'weight' attribute of first positional arg
|
"Weight in tons {0.weight}" # 'weight' attribute of first positional arg
|
||||||
"Units destroyed: {players[0]}" # First element of keyword argument 'players'.
|
"Units destroyed: {players[0]}" # First element of keyword argument 'players'.
|
||||||
|
|
||||||
The *conversion* field causes a type coercion before formatting. Normally, the
|
The *conversion* field causes a type coercion before formatting. Normally, the
|
||||||
job of formatting a value is done by the :meth:`__format__` method of the value
|
job of formatting a value is done by the :meth:`__format__` method of the value
|
||||||
|
|
|
@ -847,7 +847,7 @@ For example::
|
||||||
print("hello, world")
|
print("hello, world")
|
||||||
|
|
||||||
t = Timer(30.0, hello)
|
t = Timer(30.0, hello)
|
||||||
t.start() # after 30 seconds, "hello, world" will be printed
|
t.start() # after 30 seconds, "hello, world" will be printed
|
||||||
|
|
||||||
|
|
||||||
.. class:: Timer(interval, function, args=None, kwargs=None)
|
.. class:: Timer(interval, function, args=None, kwargs=None)
|
||||||
|
|
|
@ -206,7 +206,7 @@ A Simple Hello World Program
|
||||||
self.hi_there.pack(side="top")
|
self.hi_there.pack(side="top")
|
||||||
|
|
||||||
self.QUIT = tk.Button(self, text="QUIT", fg="red",
|
self.QUIT = tk.Button(self, text="QUIT", fg="red",
|
||||||
command=root.destroy)
|
command=root.destroy)
|
||||||
self.QUIT.pack(side="bottom")
|
self.QUIT.pack(side="bottom")
|
||||||
|
|
||||||
def say_hi(self):
|
def say_hi(self):
|
||||||
|
|
|
@ -201,7 +201,7 @@ objects::
|
||||||
we're only showing 12 digits, and the 13th isn't close to 5, the
|
we're only showing 12 digits, and the 13th isn't close to 5, the
|
||||||
rest of the output should be platform-independent.
|
rest of the output should be platform-independent.
|
||||||
|
|
||||||
>>> exec(s) #doctest: +ELLIPSIS
|
>>> exec(s) #doctest: +ELLIPSIS
|
||||||
-3.21716034272e-0...7
|
-3.21716034272e-0...7
|
||||||
|
|
||||||
Output from calculations with Decimal should be identical across all
|
Output from calculations with Decimal should be identical across all
|
||||||
|
@ -211,8 +211,8 @@ objects::
|
||||||
-3.217160342717258261933904529E-7
|
-3.217160342717258261933904529E-7
|
||||||
"""
|
"""
|
||||||
result = []
|
result = []
|
||||||
g = tokenize(BytesIO(s.encode('utf-8')).readline) # tokenize the string
|
g = tokenize(BytesIO(s.encode('utf-8')).readline) # tokenize the string
|
||||||
for toknum, tokval, _, _, _ in g:
|
for toknum, tokval, _, _, _ in g:
|
||||||
if toknum == NUMBER and '.' in tokval: # replace NUMBER tokens
|
if toknum == NUMBER and '.' in tokval: # replace NUMBER tokens
|
||||||
result.extend([
|
result.extend([
|
||||||
(NAME, 'Decimal'),
|
(NAME, 'Decimal'),
|
||||||
|
|
|
@ -252,10 +252,12 @@ Additional Utility Classes and Functions
|
||||||
class SimpleNamespace:
|
class SimpleNamespace:
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
self.__dict__.update(kwargs)
|
self.__dict__.update(kwargs)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
keys = sorted(self.__dict__)
|
keys = sorted(self.__dict__)
|
||||||
items = ("{}={!r}".format(k, self.__dict__[k]) for k in keys)
|
items = ("{}={!r}".format(k, self.__dict__[k]) for k in keys)
|
||||||
return "{}({})".format(type(self).__name__, ", ".join(items))
|
return "{}({})".format(type(self).__name__, ", ".join(items))
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return self.__dict__ == other.__dict__
|
return self.__dict__ == other.__dict__
|
||||||
|
|
||||||
|
|
|
@ -86,19 +86,19 @@ Here is a short script to test three string methods::
|
||||||
|
|
||||||
class TestStringMethods(unittest.TestCase):
|
class TestStringMethods(unittest.TestCase):
|
||||||
|
|
||||||
def test_upper(self):
|
def test_upper(self):
|
||||||
self.assertEqual('foo'.upper(), 'FOO')
|
self.assertEqual('foo'.upper(), 'FOO')
|
||||||
|
|
||||||
def test_isupper(self):
|
def test_isupper(self):
|
||||||
self.assertTrue('FOO'.isupper())
|
self.assertTrue('FOO'.isupper())
|
||||||
self.assertFalse('Foo'.isupper())
|
self.assertFalse('Foo'.isupper())
|
||||||
|
|
||||||
def test_split(self):
|
def test_split(self):
|
||||||
s = 'hello world'
|
s = 'hello world'
|
||||||
self.assertEqual(s.split(), ['hello', 'world'])
|
self.assertEqual(s.split(), ['hello', 'world'])
|
||||||
# check that s.split fails when the separator is not a string
|
# check that s.split fails when the separator is not a string
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
s.split(2)
|
s.split(2)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -1174,7 +1174,7 @@ The code for the sample CGI used in the above example is::
|
||||||
Here is an example of doing a ``PUT`` request using :class:`Request`::
|
Here is an example of doing a ``PUT`` request using :class:`Request`::
|
||||||
|
|
||||||
import urllib.request
|
import urllib.request
|
||||||
DATA=b'some data'
|
DATA = b'some data'
|
||||||
req = urllib.request.Request(url='http://localhost:8080', data=DATA,method='PUT')
|
req = urllib.request.Request(url='http://localhost:8080', data=DATA,method='PUT')
|
||||||
with urllib.request.urlopen(req) as f:
|
with urllib.request.urlopen(req) as f:
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -419,8 +419,8 @@ Paste" library.
|
||||||
# Our callable object which is intentionally not compliant to the
|
# Our callable object which is intentionally not compliant to the
|
||||||
# standard, so the validator is going to break
|
# standard, so the validator is going to break
|
||||||
def simple_app(environ, start_response):
|
def simple_app(environ, start_response):
|
||||||
status = '200 OK' # HTTP Status
|
status = '200 OK' # HTTP Status
|
||||||
headers = [('Content-type', 'text/plain')] # HTTP Headers
|
headers = [('Content-type', 'text/plain')] # HTTP Headers
|
||||||
start_response(status, headers)
|
start_response(status, headers)
|
||||||
|
|
||||||
# This is going to break because we need to return a list, and
|
# This is going to break because we need to return a list, and
|
||||||
|
@ -762,8 +762,8 @@ This is a working "Hello World" WSGI application::
|
||||||
# is a dictionary containing CGI-style environment variables and the
|
# is a dictionary containing CGI-style environment variables and the
|
||||||
# second variable is the callable object (see PEP 333).
|
# second variable is the callable object (see PEP 333).
|
||||||
def hello_world_app(environ, start_response):
|
def hello_world_app(environ, start_response):
|
||||||
status = '200 OK' # HTTP Status
|
status = '200 OK' # HTTP Status
|
||||||
headers = [('Content-type', 'text/plain; charset=utf-8')] # HTTP Headers
|
headers = [('Content-type', 'text/plain; charset=utf-8')] # HTTP Headers
|
||||||
start_response(status, headers)
|
start_response(status, headers)
|
||||||
|
|
||||||
# The returned object is going to be printed
|
# The returned object is going to be printed
|
||||||
|
|
|
@ -30,10 +30,10 @@ DOM applications typically start by parsing some XML into a DOM. With
|
||||||
|
|
||||||
from xml.dom.minidom import parse, parseString
|
from xml.dom.minidom import parse, parseString
|
||||||
|
|
||||||
dom1 = parse('c:\\temp\\mydata.xml') # parse an XML file by name
|
dom1 = parse('c:\\temp\\mydata.xml') # parse an XML file by name
|
||||||
|
|
||||||
datasource = open('c:\\temp\\mydata.xml')
|
datasource = open('c:\\temp\\mydata.xml')
|
||||||
dom2 = parse(datasource) # parse an open file
|
dom2 = parse(datasource) # parse an open file
|
||||||
|
|
||||||
dom3 = parseString('<myxml>Some data<empty/> some more data</myxml>')
|
dom3 = parseString('<myxml>Some data<empty/> some more data</myxml>')
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,7 @@ As an :class:`Element`, ``root`` has a tag and a dictionary of attributes::
|
||||||
It also has children nodes over which we can iterate::
|
It also has children nodes over which we can iterate::
|
||||||
|
|
||||||
>>> for child in root:
|
>>> for child in root:
|
||||||
... print(child.tag, child.attrib)
|
... print(child.tag, child.attrib)
|
||||||
...
|
...
|
||||||
country {'name': 'Liechtenstein'}
|
country {'name': 'Liechtenstein'}
|
||||||
country {'name': 'Singapore'}
|
country {'name': 'Singapore'}
|
||||||
|
@ -143,8 +143,8 @@ elements, call :meth:`XMLPullParser.read_events`. Here is an example::
|
||||||
[('start', <Element 'mytag' at 0x7fa66db2be58>)]
|
[('start', <Element 'mytag' at 0x7fa66db2be58>)]
|
||||||
>>> parser.feed(' more text</mytag>')
|
>>> parser.feed(' more text</mytag>')
|
||||||
>>> for event, elem in parser.read_events():
|
>>> for event, elem in parser.read_events():
|
||||||
... print(event)
|
... print(event)
|
||||||
... print(elem.tag, 'text=', elem.text)
|
... print(elem.tag, 'text=', elem.text)
|
||||||
...
|
...
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ the sub-tree below it (its children, their children, and so on). For example,
|
||||||
:meth:`Element.iter`::
|
:meth:`Element.iter`::
|
||||||
|
|
||||||
>>> for neighbor in root.iter('neighbor'):
|
>>> for neighbor in root.iter('neighbor'):
|
||||||
... print(neighbor.attrib)
|
... print(neighbor.attrib)
|
||||||
...
|
...
|
||||||
{'name': 'Austria', 'direction': 'E'}
|
{'name': 'Austria', 'direction': 'E'}
|
||||||
{'name': 'Switzerland', 'direction': 'W'}
|
{'name': 'Switzerland', 'direction': 'W'}
|
||||||
|
@ -180,9 +180,9 @@ with a particular tag, and :attr:`Element.text` accesses the element's text
|
||||||
content. :meth:`Element.get` accesses the element's attributes::
|
content. :meth:`Element.get` accesses the element's attributes::
|
||||||
|
|
||||||
>>> for country in root.findall('country'):
|
>>> for country in root.findall('country'):
|
||||||
... rank = country.find('rank').text
|
... rank = country.find('rank').text
|
||||||
... name = country.get('name')
|
... name = country.get('name')
|
||||||
... print(name, rank)
|
... print(name, rank)
|
||||||
...
|
...
|
||||||
Liechtenstein 1
|
Liechtenstein 1
|
||||||
Singapore 4
|
Singapore 4
|
||||||
|
@ -206,9 +206,9 @@ Let's say we want to add one to each country's rank, and add an ``updated``
|
||||||
attribute to the rank element::
|
attribute to the rank element::
|
||||||
|
|
||||||
>>> for rank in root.iter('rank'):
|
>>> for rank in root.iter('rank'):
|
||||||
... new_rank = int(rank.text) + 1
|
... new_rank = int(rank.text) + 1
|
||||||
... rank.text = str(new_rank)
|
... rank.text = str(new_rank)
|
||||||
... rank.set('updated', 'yes')
|
... rank.set('updated', 'yes')
|
||||||
...
|
...
|
||||||
>>> tree.write('output.xml')
|
>>> tree.write('output.xml')
|
||||||
|
|
||||||
|
@ -244,9 +244,9 @@ We can remove elements using :meth:`Element.remove`. Let's say we want to
|
||||||
remove all countries with a rank higher than 50::
|
remove all countries with a rank higher than 50::
|
||||||
|
|
||||||
>>> for country in root.findall('country'):
|
>>> for country in root.findall('country'):
|
||||||
... rank = int(country.find('rank').text)
|
... rank = int(country.find('rank').text)
|
||||||
... if rank > 50:
|
... if rank > 50:
|
||||||
... root.remove(country)
|
... root.remove(country)
|
||||||
...
|
...
|
||||||
>>> tree.write('output.xml')
|
>>> tree.write('output.xml')
|
||||||
|
|
||||||
|
|
|
@ -216,7 +216,7 @@ A working example follows. The server code::
|
||||||
from xmlrpc.server import SimpleXMLRPCServer
|
from xmlrpc.server import SimpleXMLRPCServer
|
||||||
|
|
||||||
def is_even(n):
|
def is_even(n):
|
||||||
return n%2 == 0
|
return n % 2 == 0
|
||||||
|
|
||||||
server = SimpleXMLRPCServer(("localhost", 8000))
|
server = SimpleXMLRPCServer(("localhost", 8000))
|
||||||
print("Listening on port 8000...")
|
print("Listening on port 8000...")
|
||||||
|
@ -373,7 +373,7 @@ returning a complex type object. The server code::
|
||||||
|
|
||||||
# A marshalling error is going to occur because we're returning a
|
# A marshalling error is going to occur because we're returning a
|
||||||
# complex number
|
# complex number
|
||||||
def add(x,y):
|
def add(x, y):
|
||||||
return x+y+0j
|
return x+y+0j
|
||||||
|
|
||||||
server = SimpleXMLRPCServer(("localhost", 8000))
|
server = SimpleXMLRPCServer(("localhost", 8000))
|
||||||
|
@ -566,12 +566,15 @@ transport. The following example shows how:
|
||||||
class ProxiedTransport(xmlrpc.client.Transport):
|
class ProxiedTransport(xmlrpc.client.Transport):
|
||||||
def set_proxy(self, proxy):
|
def set_proxy(self, proxy):
|
||||||
self.proxy = proxy
|
self.proxy = proxy
|
||||||
|
|
||||||
def make_connection(self, host):
|
def make_connection(self, host):
|
||||||
self.realhost = host
|
self.realhost = host
|
||||||
h = http.client.HTTPConnection(self.proxy)
|
h = http.client.HTTPConnection(self.proxy)
|
||||||
return h
|
return h
|
||||||
|
|
||||||
def send_request(self, connection, handler, request_body, debug):
|
def send_request(self, connection, handler, request_body, debug):
|
||||||
connection.putrequest("POST", 'http://%s%s' % (self.realhost, handler))
|
connection.putrequest("POST", 'http://%s%s' % (self.realhost, handler))
|
||||||
|
|
||||||
def send_host(self, connection, host):
|
def send_host(self, connection, host):
|
||||||
connection.putheader('Host', self.realhost)
|
connection.putheader('Host', self.realhost)
|
||||||
|
|
||||||
|
|
|
@ -1753,11 +1753,11 @@ to remember the order that class variables are defined::
|
||||||
|
|
||||||
class OrderedClass(type):
|
class OrderedClass(type):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def __prepare__(metacls, name, bases, **kwds):
|
def __prepare__(metacls, name, bases, **kwds):
|
||||||
return collections.OrderedDict()
|
return collections.OrderedDict()
|
||||||
|
|
||||||
def __new__(cls, name, bases, namespace, **kwds):
|
def __new__(cls, name, bases, namespace, **kwds):
|
||||||
result = type.__new__(cls, name, bases, dict(namespace))
|
result = type.__new__(cls, name, bases, dict(namespace))
|
||||||
result.members = tuple(namespace)
|
result.members = tuple(namespace)
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -728,7 +728,7 @@ A consequence of this is that although the ``*expression`` syntax may appear
|
||||||
(and the ``**expression`` argument, if any -- see below). So::
|
(and the ``**expression`` argument, if any -- see below). So::
|
||||||
|
|
||||||
>>> def f(a, b):
|
>>> def f(a, b):
|
||||||
... print(a, b)
|
... print(a, b)
|
||||||
...
|
...
|
||||||
>>> f(b=1, *(2,))
|
>>> f(b=1, *(2,))
|
||||||
2 1
|
2 1
|
||||||
|
|
|
@ -331,12 +331,12 @@ program:
|
||||||
The simple form, ``assert expression``, is equivalent to ::
|
The simple form, ``assert expression``, is equivalent to ::
|
||||||
|
|
||||||
if __debug__:
|
if __debug__:
|
||||||
if not expression: raise AssertionError
|
if not expression: raise AssertionError
|
||||||
|
|
||||||
The extended form, ``assert expression1, expression2``, is equivalent to ::
|
The extended form, ``assert expression1, expression2``, is equivalent to ::
|
||||||
|
|
||||||
if __debug__:
|
if __debug__:
|
||||||
if not expression1: raise AssertionError(expression2)
|
if not expression1: raise AssertionError(expression2)
|
||||||
|
|
||||||
.. index::
|
.. index::
|
||||||
single: __debug__
|
single: __debug__
|
||||||
|
|
|
@ -92,7 +92,7 @@ in the script::
|
||||||
filename = os.environ.get('PYTHONSTARTUP')
|
filename = os.environ.get('PYTHONSTARTUP')
|
||||||
if filename and os.path.isfile(filename):
|
if filename and os.path.isfile(filename):
|
||||||
with open(filename) as fobj:
|
with open(filename) as fobj:
|
||||||
startup_file = fobj.read()
|
startup_file = fobj.read()
|
||||||
exec(startup_file)
|
exec(startup_file)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -162,12 +162,15 @@ binding::
|
||||||
def scope_test():
|
def scope_test():
|
||||||
def do_local():
|
def do_local():
|
||||||
spam = "local spam"
|
spam = "local spam"
|
||||||
|
|
||||||
def do_nonlocal():
|
def do_nonlocal():
|
||||||
nonlocal spam
|
nonlocal spam
|
||||||
spam = "nonlocal spam"
|
spam = "nonlocal spam"
|
||||||
|
|
||||||
def do_global():
|
def do_global():
|
||||||
global spam
|
global spam
|
||||||
spam = "global spam"
|
spam = "global spam"
|
||||||
|
|
||||||
spam = "test spam"
|
spam = "test spam"
|
||||||
do_local()
|
do_local()
|
||||||
print("After local assignment:", spam)
|
print("After local assignment:", spam)
|
||||||
|
@ -260,6 +263,7 @@ definition looked like this::
|
||||||
class MyClass:
|
class MyClass:
|
||||||
"""A simple example class"""
|
"""A simple example class"""
|
||||||
i = 12345
|
i = 12345
|
||||||
|
|
||||||
def f(self):
|
def f(self):
|
||||||
return 'hello world'
|
return 'hello world'
|
||||||
|
|
||||||
|
@ -508,8 +512,10 @@ variable in the class is also ok. For example::
|
||||||
|
|
||||||
class C:
|
class C:
|
||||||
f = f1
|
f = f1
|
||||||
|
|
||||||
def g(self):
|
def g(self):
|
||||||
return 'hello world'
|
return 'hello world'
|
||||||
|
|
||||||
h = g
|
h = g
|
||||||
|
|
||||||
Now ``f``, ``g`` and ``h`` are all attributes of class :class:`C` that refer to
|
Now ``f``, ``g`` and ``h`` are all attributes of class :class:`C` that refer to
|
||||||
|
@ -523,8 +529,10 @@ argument::
|
||||||
class Bag:
|
class Bag:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.data = []
|
self.data = []
|
||||||
|
|
||||||
def add(self, x):
|
def add(self, x):
|
||||||
self.data.append(x)
|
self.data.append(x)
|
||||||
|
|
||||||
def addtwice(self, x):
|
def addtwice(self, x):
|
||||||
self.add(x)
|
self.add(x)
|
||||||
self.add(x)
|
self.add(x)
|
||||||
|
@ -713,7 +721,7 @@ will do nicely::
|
||||||
class Employee:
|
class Employee:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
john = Employee() # Create an empty employee record
|
john = Employee() # Create an empty employee record
|
||||||
|
|
||||||
# Fill the fields of the record
|
# Fill the fields of the record
|
||||||
john.name = 'John Doe'
|
john.name = 'John Doe'
|
||||||
|
@ -839,8 +847,10 @@ defines :meth:`__next__`, then :meth:`__iter__` can just return ``self``::
|
||||||
def __init__(self, data):
|
def __init__(self, data):
|
||||||
self.data = data
|
self.data = data
|
||||||
self.index = len(data)
|
self.index = len(data)
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __next__(self):
|
def __next__(self):
|
||||||
if self.index == 0:
|
if self.index == 0:
|
||||||
raise StopIteration
|
raise StopIteration
|
||||||
|
|
|
@ -312,7 +312,7 @@ You can see it if you really want to using :func:`print`::
|
||||||
It is simple to write a function that returns a list of the numbers of the
|
It is simple to write a function that returns a list of the numbers of the
|
||||||
Fibonacci series, instead of printing it::
|
Fibonacci series, instead of printing it::
|
||||||
|
|
||||||
>>> def fib2(n): # return Fibonacci series up to n
|
>>> def fib2(n): # return Fibonacci series up to n
|
||||||
... """Return a list containing the Fibonacci series up to n."""
|
... """Return a list containing the Fibonacci series up to n."""
|
||||||
... result = []
|
... result = []
|
||||||
... a, b = 0, 1
|
... a, b = 0, 1
|
||||||
|
@ -540,7 +540,7 @@ parameter are 'keyword-only' arguments, meaning that they can only be used as
|
||||||
keywords rather than positional arguments. ::
|
keywords rather than positional arguments. ::
|
||||||
|
|
||||||
>>> def concat(*args, sep="/"):
|
>>> def concat(*args, sep="/"):
|
||||||
... return sep.join(args)
|
... return sep.join(args)
|
||||||
...
|
...
|
||||||
>>> concat("earth", "mars", "venus")
|
>>> concat("earth", "mars", "venus")
|
||||||
'earth/mars/venus'
|
'earth/mars/venus'
|
||||||
|
|
|
@ -170,15 +170,15 @@ reference ``.args``. One may also instantiate an exception first before
|
||||||
raising it and add any attributes to it as desired. ::
|
raising it and add any attributes to it as desired. ::
|
||||||
|
|
||||||
>>> try:
|
>>> try:
|
||||||
... raise Exception('spam', 'eggs')
|
... raise Exception('spam', 'eggs')
|
||||||
... except Exception as inst:
|
... except Exception as inst:
|
||||||
... print(type(inst)) # the exception instance
|
... print(type(inst)) # the exception instance
|
||||||
... print(inst.args) # arguments stored in .args
|
... print(inst.args) # arguments stored in .args
|
||||||
... print(inst) # __str__ allows args to be printed directly,
|
... print(inst) # __str__ allows args to be printed directly,
|
||||||
... # but may be overridden in exception subclasses
|
... # but may be overridden in exception subclasses
|
||||||
... x, y = inst.args # unpack args
|
... x, y = inst.args # unpack args
|
||||||
... print('x =', x)
|
... print('x =', x)
|
||||||
... print('y =', y)
|
... print('y =', y)
|
||||||
...
|
...
|
||||||
<class 'Exception'>
|
<class 'Exception'>
|
||||||
('spam', 'eggs')
|
('spam', 'eggs')
|
||||||
|
|
|
@ -338,11 +338,11 @@ beginning of the file as the reference point. ::
|
||||||
>>> f = open('workfile', 'rb+')
|
>>> f = open('workfile', 'rb+')
|
||||||
>>> f.write(b'0123456789abcdef')
|
>>> f.write(b'0123456789abcdef')
|
||||||
16
|
16
|
||||||
>>> f.seek(5) # Go to the 6th byte in the file
|
>>> f.seek(5) # Go to the 6th byte in the file
|
||||||
5
|
5
|
||||||
>>> f.read(1)
|
>>> f.read(1)
|
||||||
b'5'
|
b'5'
|
||||||
>>> f.seek(-3, 2) # Go to the 3rd byte before the end
|
>>> f.seek(-3, 2) # Go to the 3rd byte before the end
|
||||||
13
|
13
|
||||||
>>> f.read(1)
|
>>> f.read(1)
|
||||||
b'd'
|
b'd'
|
||||||
|
|
|
@ -232,7 +232,7 @@ If you want to concatenate variables or a variable and a literal, use ``+``::
|
||||||
This feature is particularly useful when you want to break long strings::
|
This feature is particularly useful when you want to break long strings::
|
||||||
|
|
||||||
>>> text = ('Put several strings within parentheses '
|
>>> text = ('Put several strings within parentheses '
|
||||||
'to have them joined together.')
|
... 'to have them joined together.')
|
||||||
>>> text
|
>>> text
|
||||||
'Put several strings within parentheses to have them joined together.'
|
'Put several strings within parentheses to have them joined together.'
|
||||||
|
|
||||||
|
@ -276,11 +276,11 @@ makes sure that ``s[:i] + s[i:]`` is always equal to ``s``::
|
||||||
Slice indices have useful defaults; an omitted first index defaults to zero, an
|
Slice indices have useful defaults; an omitted first index defaults to zero, an
|
||||||
omitted second index defaults to the size of the string being sliced. ::
|
omitted second index defaults to the size of the string being sliced. ::
|
||||||
|
|
||||||
>>> word[:2] # character from the beginning to position 2 (excluded)
|
>>> word[:2] # character from the beginning to position 2 (excluded)
|
||||||
'Py'
|
'Py'
|
||||||
>>> word[4:] # characters from position 4 (included) to the end
|
>>> word[4:] # characters from position 4 (included) to the end
|
||||||
'on'
|
'on'
|
||||||
>>> word[-2:] # characters from the second-last (included) to the end
|
>>> word[-2:] # characters from the second-last (included) to the end
|
||||||
'on'
|
'on'
|
||||||
|
|
||||||
One way to remember how slices work is to think of the indices as pointing
|
One way to remember how slices work is to think of the indices as pointing
|
||||||
|
|
|
@ -34,7 +34,7 @@ called :file:`fibo.py` in the current directory with the following contents::
|
||||||
a, b = b, a+b
|
a, b = b, a+b
|
||||||
print()
|
print()
|
||||||
|
|
||||||
def fib2(n): # return Fibonacci series up to n
|
def fib2(n): # return Fibonacci series up to n
|
||||||
result = []
|
result = []
|
||||||
a, b = 0, 1
|
a, b = 0, 1
|
||||||
while b < n:
|
while b < n:
|
||||||
|
|
|
@ -301,7 +301,7 @@ file::
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
average(20, 30, 70)
|
average(20, 30, 70)
|
||||||
|
|
||||||
unittest.main() # Calling from the command line invokes all tests
|
unittest.main() # Calling from the command line invokes all tests
|
||||||
|
|
||||||
|
|
||||||
.. _tut-batteries-included:
|
.. _tut-batteries-included:
|
||||||
|
|
|
@ -180,6 +180,7 @@ tasks in background while the main program continues to run::
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
self.infile = infile
|
self.infile = infile
|
||||||
self.outfile = outfile
|
self.outfile = outfile
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
f = zipfile.ZipFile(self.outfile, 'w', zipfile.ZIP_DEFLATED)
|
f = zipfile.ZipFile(self.outfile, 'w', zipfile.ZIP_DEFLATED)
|
||||||
f.write(self.infile)
|
f.write(self.infile)
|
||||||
|
|
|
@ -116,7 +116,7 @@ or more positional arguments is present, and making a required option::
|
||||||
|
|
||||||
Example of calling the parser on a command string::
|
Example of calling the parser on a command string::
|
||||||
|
|
||||||
>>> cmd = 'deploy sneezy.example.com sleepy.example.com -u skycaptain'
|
>>> cmd = 'deploy sneezy.example.com sleepy.example.com -u skycaptain'
|
||||||
>>> result = parser.parse_args(cmd.split())
|
>>> result = parser.parse_args(cmd.split())
|
||||||
>>> result.action
|
>>> result.action
|
||||||
'deploy'
|
'deploy'
|
||||||
|
@ -212,7 +212,8 @@ loaded and called with code like this::
|
||||||
|
|
||||||
>>> import json, logging.config
|
>>> import json, logging.config
|
||||||
>>> with open('conf.json') as f:
|
>>> with open('conf.json') as f:
|
||||||
conf = json.load(f)
|
... conf = json.load(f)
|
||||||
|
...
|
||||||
>>> logging.config.dictConfig(conf)
|
>>> logging.config.dictConfig(conf)
|
||||||
>>> logging.info("Transaction completed normally")
|
>>> logging.info("Transaction completed normally")
|
||||||
INFO : root : Transaction completed normally
|
INFO : root : Transaction completed normally
|
||||||
|
@ -460,15 +461,15 @@ Some smaller changes made to the core Python language are:
|
||||||
'The testing project status is green as of February 15, 2011'
|
'The testing project status is green as of February 15, 2011'
|
||||||
|
|
||||||
>>> class LowerCasedDict(dict):
|
>>> class LowerCasedDict(dict):
|
||||||
def __getitem__(self, key):
|
... def __getitem__(self, key):
|
||||||
return dict.__getitem__(self, key.lower())
|
... return dict.__getitem__(self, key.lower())
|
||||||
>>> lcd = LowerCasedDict(part='widgets', quantity=10)
|
>>> lcd = LowerCasedDict(part='widgets', quantity=10)
|
||||||
>>> 'There are {QUANTITY} {Part} in stock'.format_map(lcd)
|
>>> 'There are {QUANTITY} {Part} in stock'.format_map(lcd)
|
||||||
'There are 10 widgets in stock'
|
'There are 10 widgets in stock'
|
||||||
|
|
||||||
>>> class PlaceholderDict(dict):
|
>>> class PlaceholderDict(dict):
|
||||||
def __missing__(self, key):
|
... def __missing__(self, key):
|
||||||
return '<{}>'.format(key)
|
... return '<{}>'.format(key)
|
||||||
>>> 'Hello {name}, welcome to {location}'.format_map(PlaceholderDict())
|
>>> 'Hello {name}, welcome to {location}'.format_map(PlaceholderDict())
|
||||||
'Hello <name>, welcome to <location>'
|
'Hello <name>, welcome to <location>'
|
||||||
|
|
||||||
|
@ -496,10 +497,10 @@ Some smaller changes made to the core Python language are:
|
||||||
exceptions pass through::
|
exceptions pass through::
|
||||||
|
|
||||||
>>> class A:
|
>>> class A:
|
||||||
@property
|
... @property
|
||||||
def f(self):
|
... def f(self):
|
||||||
return 1 // 0
|
... return 1 // 0
|
||||||
|
...
|
||||||
>>> a = A()
|
>>> a = A()
|
||||||
>>> hasattr(a, 'f')
|
>>> hasattr(a, 'f')
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
|
@ -537,7 +538,7 @@ Some smaller changes made to the core Python language are:
|
||||||
|
|
||||||
def outer(x):
|
def outer(x):
|
||||||
def inner():
|
def inner():
|
||||||
return x
|
return x
|
||||||
inner()
|
inner()
|
||||||
del x
|
del x
|
||||||
|
|
||||||
|
@ -547,12 +548,12 @@ Some smaller changes made to the core Python language are:
|
||||||
|
|
||||||
def f():
|
def f():
|
||||||
def print_error():
|
def print_error():
|
||||||
print(e)
|
print(e)
|
||||||
try:
|
try:
|
||||||
something
|
something
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print_error()
|
print_error()
|
||||||
# implicit "del e" here
|
# implicit "del e" here
|
||||||
|
|
||||||
(See :issue:`4617`.)
|
(See :issue:`4617`.)
|
||||||
|
|
||||||
|
@ -799,6 +800,7 @@ functools
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return ((self.lastname.lower(), self.firstname.lower()) ==
|
return ((self.lastname.lower(), self.firstname.lower()) ==
|
||||||
(other.lastname.lower(), other.firstname.lower()))
|
(other.lastname.lower(), other.firstname.lower()))
|
||||||
|
|
||||||
def __lt__(self, other):
|
def __lt__(self, other):
|
||||||
return ((self.lastname.lower(), self.firstname.lower()) <
|
return ((self.lastname.lower(), self.firstname.lower()) <
|
||||||
(other.lastname.lower(), other.firstname.lower()))
|
(other.lastname.lower(), other.firstname.lower()))
|
||||||
|
@ -942,7 +944,7 @@ released and a :exc:`~threading.BrokenBarrierError` exception is raised::
|
||||||
def get_votes(site):
|
def get_votes(site):
|
||||||
ballots = conduct_election(site)
|
ballots = conduct_election(site)
|
||||||
try:
|
try:
|
||||||
all_polls_closed.wait(timeout = midnight - time.now())
|
all_polls_closed.wait(timeout=midnight - time.now())
|
||||||
except BrokenBarrierError:
|
except BrokenBarrierError:
|
||||||
lockbox = seal_ballots(ballots)
|
lockbox = seal_ballots(ballots)
|
||||||
queue.put(lockbox)
|
queue.put(lockbox)
|
||||||
|
@ -1097,16 +1099,16 @@ for slice notation are well-suited to in-place editing::
|
||||||
>>> REC_LEN, LOC_START, LOC_LEN = 34, 7, 11
|
>>> REC_LEN, LOC_START, LOC_LEN = 34, 7, 11
|
||||||
|
|
||||||
>>> def change_location(buffer, record_number, location):
|
>>> def change_location(buffer, record_number, location):
|
||||||
start = record_number * REC_LEN + LOC_START
|
... start = record_number * REC_LEN + LOC_START
|
||||||
buffer[start: start+LOC_LEN] = location
|
... buffer[start: start+LOC_LEN] = location
|
||||||
|
|
||||||
>>> import io
|
>>> import io
|
||||||
|
|
||||||
>>> byte_stream = io.BytesIO(
|
>>> byte_stream = io.BytesIO(
|
||||||
b'G3805 storeroom Main chassis '
|
... b'G3805 storeroom Main chassis '
|
||||||
b'X7899 shipping Reserve cog '
|
... b'X7899 shipping Reserve cog '
|
||||||
b'L6988 receiving Primary sprocket'
|
... b'L6988 receiving Primary sprocket'
|
||||||
)
|
... )
|
||||||
>>> buffer = byte_stream.getbuffer()
|
>>> buffer = byte_stream.getbuffer()
|
||||||
>>> change_location(buffer, 1, b'warehouse ')
|
>>> change_location(buffer, 1, b'warehouse ')
|
||||||
>>> change_location(buffer, 0, b'showroom ')
|
>>> change_location(buffer, 0, b'showroom ')
|
||||||
|
@ -1131,10 +1133,10 @@ decorator, :func:`~reprlib.recursive_repr`, for detecting recursive calls to
|
||||||
:meth:`__repr__` and substituting a placeholder string instead::
|
:meth:`__repr__` and substituting a placeholder string instead::
|
||||||
|
|
||||||
>>> class MyList(list):
|
>>> class MyList(list):
|
||||||
@recursive_repr()
|
... @recursive_repr()
|
||||||
def __repr__(self):
|
... def __repr__(self):
|
||||||
return '<' + '|'.join(map(repr, self)) + '>'
|
... return '<' + '|'.join(map(repr, self)) + '>'
|
||||||
|
...
|
||||||
>>> m = MyList('abc')
|
>>> m = MyList('abc')
|
||||||
>>> m.append(m)
|
>>> m.append(m)
|
||||||
>>> m.append('x')
|
>>> m.append('x')
|
||||||
|
@ -1197,8 +1199,8 @@ the field names::
|
||||||
>>> w.writeheader()
|
>>> w.writeheader()
|
||||||
"name","dept"
|
"name","dept"
|
||||||
>>> w.writerows([
|
>>> w.writerows([
|
||||||
{'name': 'tom', 'dept': 'accounting'},
|
... {'name': 'tom', 'dept': 'accounting'},
|
||||||
{'name': 'susan', 'dept': 'Salesl'}])
|
... {'name': 'susan', 'dept': 'Salesl'}])
|
||||||
"tom","accounting"
|
"tom","accounting"
|
||||||
"susan","sales"
|
"susan","sales"
|
||||||
|
|
||||||
|
@ -1423,14 +1425,14 @@ function can return *None*::
|
||||||
>>> import tarfile, glob
|
>>> import tarfile, glob
|
||||||
|
|
||||||
>>> def myfilter(tarinfo):
|
>>> def myfilter(tarinfo):
|
||||||
if tarinfo.isfile(): # only save real files
|
... if tarinfo.isfile(): # only save real files
|
||||||
tarinfo.uname = 'monty' # redact the user name
|
... tarinfo.uname = 'monty' # redact the user name
|
||||||
return tarinfo
|
... return tarinfo
|
||||||
|
|
||||||
>>> with tarfile.open(name='myarchive.tar.gz', mode='w:gz') as tf:
|
>>> with tarfile.open(name='myarchive.tar.gz', mode='w:gz') as tf:
|
||||||
for filename in glob.glob('*.txt'):
|
... for filename in glob.glob('*.txt'):
|
||||||
tf.add(filename, filter=myfilter)
|
... tf.add(filename, filter=myfilter)
|
||||||
tf.list()
|
... tf.list()
|
||||||
-rw-r--r-- monty/501 902 2011-01-26 17:59:11 annotations.txt
|
-rw-r--r-- monty/501 902 2011-01-26 17:59:11 annotations.txt
|
||||||
-rw-r--r-- monty/501 123 2011-01-26 17:59:11 general_questions.txt
|
-rw-r--r-- monty/501 123 2011-01-26 17:59:11 general_questions.txt
|
||||||
-rw-r--r-- monty/501 3514 2011-01-26 17:59:11 prion.txt
|
-rw-r--r-- monty/501 3514 2011-01-26 17:59:11 prion.txt
|
||||||
|
@ -1536,26 +1538,26 @@ step is non-destructive (the original files are left unchanged).
|
||||||
|
|
||||||
>>> import shutil, pprint
|
>>> import shutil, pprint
|
||||||
|
|
||||||
>>> os.chdir('mydata') # change to the source directory
|
>>> os.chdir('mydata') # change to the source directory
|
||||||
>>> f = shutil.make_archive('/var/backup/mydata',
|
>>> f = shutil.make_archive('/var/backup/mydata',
|
||||||
'zip') # archive the current directory
|
... 'zip') # archive the current directory
|
||||||
>>> f # show the name of archive
|
>>> f # show the name of archive
|
||||||
'/var/backup/mydata.zip'
|
'/var/backup/mydata.zip'
|
||||||
>>> os.chdir('tmp') # change to an unpacking
|
>>> os.chdir('tmp') # change to an unpacking
|
||||||
>>> shutil.unpack_archive('/var/backup/mydata.zip') # recover the data
|
>>> shutil.unpack_archive('/var/backup/mydata.zip') # recover the data
|
||||||
|
|
||||||
>>> pprint.pprint(shutil.get_archive_formats()) # display known formats
|
>>> pprint.pprint(shutil.get_archive_formats()) # display known formats
|
||||||
[('bztar', "bzip2'ed tar-file"),
|
[('bztar', "bzip2'ed tar-file"),
|
||||||
('gztar', "gzip'ed tar-file"),
|
('gztar', "gzip'ed tar-file"),
|
||||||
('tar', 'uncompressed tar file'),
|
('tar', 'uncompressed tar file'),
|
||||||
('zip', 'ZIP file')]
|
('zip', 'ZIP file')]
|
||||||
|
|
||||||
>>> shutil.register_archive_format( # register a new archive format
|
>>> shutil.register_archive_format( # register a new archive format
|
||||||
name = 'xz',
|
... name='xz',
|
||||||
function = xz.compress, # callable archiving function
|
... function=xz.compress, # callable archiving function
|
||||||
extra_args = [('level', 8)], # arguments to the function
|
... extra_args=[('level', 8)], # arguments to the function
|
||||||
description = 'xz compression'
|
... description='xz compression'
|
||||||
)
|
... )
|
||||||
|
|
||||||
(Contributed by Tarek Ziadé.)
|
(Contributed by Tarek Ziadé.)
|
||||||
|
|
||||||
|
@ -1854,7 +1856,7 @@ inspect
|
||||||
|
|
||||||
>>> from inspect import getgeneratorstate
|
>>> from inspect import getgeneratorstate
|
||||||
>>> def gen():
|
>>> def gen():
|
||||||
yield 'demo'
|
... yield 'demo'
|
||||||
>>> g = gen()
|
>>> g = gen()
|
||||||
>>> getgeneratorstate(g)
|
>>> getgeneratorstate(g)
|
||||||
'GEN_CREATED'
|
'GEN_CREATED'
|
||||||
|
@ -1874,11 +1876,11 @@ inspect
|
||||||
change state while it is searching::
|
change state while it is searching::
|
||||||
|
|
||||||
>>> class A:
|
>>> class A:
|
||||||
@property
|
... @property
|
||||||
def f(self):
|
... def f(self):
|
||||||
print('Running')
|
... print('Running')
|
||||||
return 10
|
... return 10
|
||||||
|
...
|
||||||
>>> a = A()
|
>>> a = A()
|
||||||
>>> getattr(a, 'f')
|
>>> getattr(a, 'f')
|
||||||
Running
|
Running
|
||||||
|
@ -2102,19 +2104,19 @@ Config parsers gained a new API based on the mapping protocol::
|
||||||
|
|
||||||
>>> parser = ConfigParser()
|
>>> parser = ConfigParser()
|
||||||
>>> parser.read_string("""
|
>>> parser.read_string("""
|
||||||
[DEFAULT]
|
... [DEFAULT]
|
||||||
location = upper left
|
... location = upper left
|
||||||
visible = yes
|
... visible = yes
|
||||||
editable = no
|
... editable = no
|
||||||
color = blue
|
... color = blue
|
||||||
|
...
|
||||||
[main]
|
... [main]
|
||||||
title = Main Menu
|
... title = Main Menu
|
||||||
color = green
|
... color = green
|
||||||
|
...
|
||||||
[options]
|
... [options]
|
||||||
title = Options
|
... title = Options
|
||||||
""")
|
... """)
|
||||||
>>> parser['main']['color']
|
>>> parser['main']['color']
|
||||||
'green'
|
'green'
|
||||||
>>> parser['main']['editable']
|
>>> parser['main']['editable']
|
||||||
|
@ -2138,24 +2140,24 @@ handler :class:`~configparser.ExtendedInterpolation`::
|
||||||
|
|
||||||
>>> parser = ConfigParser(interpolation=ExtendedInterpolation())
|
>>> parser = ConfigParser(interpolation=ExtendedInterpolation())
|
||||||
>>> parser.read_dict({'buildout': {'directory': '/home/ambv/zope9'},
|
>>> parser.read_dict({'buildout': {'directory': '/home/ambv/zope9'},
|
||||||
'custom': {'prefix': '/usr/local'}})
|
... 'custom': {'prefix': '/usr/local'}})
|
||||||
>>> parser.read_string("""
|
>>> parser.read_string("""
|
||||||
[buildout]
|
... [buildout]
|
||||||
parts =
|
... parts =
|
||||||
zope9
|
... zope9
|
||||||
instance
|
... instance
|
||||||
find-links =
|
... find-links =
|
||||||
${buildout:directory}/downloads/dist
|
... ${buildout:directory}/downloads/dist
|
||||||
|
...
|
||||||
[zope9]
|
... [zope9]
|
||||||
recipe = plone.recipe.zope9install
|
... recipe = plone.recipe.zope9install
|
||||||
location = /opt/zope
|
... location = /opt/zope
|
||||||
|
...
|
||||||
[instance]
|
... [instance]
|
||||||
recipe = plone.recipe.zope9instance
|
... recipe = plone.recipe.zope9instance
|
||||||
zope9-location = ${zope9:location}
|
... zope9-location = ${zope9:location}
|
||||||
zope-conf = ${custom:prefix}/etc/zope.conf
|
... zope-conf = ${custom:prefix}/etc/zope.conf
|
||||||
""")
|
... """)
|
||||||
>>> parser['buildout']['find-links']
|
>>> parser['buildout']['find-links']
|
||||||
'\n/home/ambv/zope9/downloads/dist'
|
'\n/home/ambv/zope9/downloads/dist'
|
||||||
>>> parser['instance']['zope-conf']
|
>>> parser['instance']['zope-conf']
|
||||||
|
@ -2207,9 +2209,9 @@ string, then the *safe*, *encoding*, and *error* parameters are sent to
|
||||||
:func:`~urllib.parse.quote_plus` for encoding::
|
:func:`~urllib.parse.quote_plus` for encoding::
|
||||||
|
|
||||||
>>> urllib.parse.urlencode([
|
>>> urllib.parse.urlencode([
|
||||||
('type', 'telenovela'),
|
... ('type', 'telenovela'),
|
||||||
('name', '¿Dónde Está Elisa?')],
|
... ('name', '¿Dónde Está Elisa?')],
|
||||||
encoding='latin-1')
|
... encoding='latin-1')
|
||||||
'type=telenovela&name=%BFD%F3nde+Est%E1+Elisa%3F'
|
'type=telenovela&name=%BFD%F3nde+Est%E1+Elisa%3F'
|
||||||
|
|
||||||
As detailed in :ref:`parsing-ascii-encoded-bytes`, all the :mod:`urllib.parse`
|
As detailed in :ref:`parsing-ascii-encoded-bytes`, all the :mod:`urllib.parse`
|
||||||
|
|
|
@ -440,15 +440,15 @@ return a final value to the outer generator::
|
||||||
...
|
...
|
||||||
>>> tallies = []
|
>>> tallies = []
|
||||||
>>> acc = gather_tallies(tallies)
|
>>> acc = gather_tallies(tallies)
|
||||||
>>> next(acc) # Ensure the accumulator is ready to accept values
|
>>> next(acc) # Ensure the accumulator is ready to accept values
|
||||||
>>> for i in range(4):
|
>>> for i in range(4):
|
||||||
... acc.send(i)
|
... acc.send(i)
|
||||||
...
|
...
|
||||||
>>> acc.send(None) # Finish the first tally
|
>>> acc.send(None) # Finish the first tally
|
||||||
>>> for i in range(5):
|
>>> for i in range(5):
|
||||||
... acc.send(i)
|
... acc.send(i)
|
||||||
...
|
...
|
||||||
>>> acc.send(None) # Finish the second tally
|
>>> acc.send(None) # Finish the second tally
|
||||||
>>> tallies
|
>>> tallies
|
||||||
[6, 10]
|
[6, 10]
|
||||||
|
|
||||||
|
|
|
@ -746,7 +746,7 @@ optional *current_offset*), and the resulting object can be iterated to produce
|
||||||
method, equivalent to calling :mod:`~dis.dis` on the constructor argument, but
|
method, equivalent to calling :mod:`~dis.dis` on the constructor argument, but
|
||||||
returned as a multi-line string::
|
returned as a multi-line string::
|
||||||
|
|
||||||
>>> bytecode = dis.Bytecode(lambda x: x +1, current_offset=3)
|
>>> bytecode = dis.Bytecode(lambda x: x + 1, current_offset=3)
|
||||||
>>> for instr in bytecode:
|
>>> for instr in bytecode:
|
||||||
... print('{} ({})'.format(instr.opname, instr.opcode))
|
... print('{} ({})'.format(instr.opname, instr.opcode))
|
||||||
LOAD_FAST (124)
|
LOAD_FAST (124)
|
||||||
|
|
Loading…
Reference in New Issue