I lost previous post :(
openssl req -x509 -nodes -newkey rsa:2048 -days 3650 -keyout server.pem -out server.pem
Просто мои записки и не более того, как раньше говорил апач "Move along, nothing to see here ;)"
openssl req -x509 -nodes -newkey rsa:2048 -days 3650 -keyout server.pem -out server.pem
>>> def foo(bar=[]): # bar is optional and defaults to [] if not specified
... bar.append("baz") # but this line could be problematic, as we'll see...
... return bar
A common mistake is to think that the optional argument will be set to the specified default expression each time
the function is called without supplying a value for the optional
argument. In the above code, for example, one might expect that calling
foo()
repeatedly (i.e., without specifying a bar
argument) would always return 'baz'
, since the assumption would be that each time foo()
is called (without a bar
argument specified) bar
is set to []
(i.e., a new empty list).>>> foo()
["baz"]
>>> foo()
["baz", "baz"]
>>> foo()
["baz", "baz", "baz"]
Huh? Why did it keep appending the default value of "baz"
to an existing list each time foo()
was called, rather than creating a new list each time?bar
argument is initialized to its default (i.e., an empty list) only when foo()
is first defined, but then calls to foo()
(i.e., without a bar
argument specified) will continue to use the same list to which bar
was originally initialized.>>> def foo(bar=None):
... if bar is None: # or if not bar:
... bar = []
... bar.append("baz")
... return bar
...
>>> foo()
["baz"]
>>> foo()
["baz"]
>>> foo()
["baz"]
>>> class A(object):
... x = 1
...
>>> class B(A):
... pass
...
>>> class C(A):
... pass
...
>>> print A.x, B.x, C.x
1 1 1
Makes sense.>>> B.x = 2
>>> print A.x, B.x, C.x
1 2 1
Yup, again as expected.>>> A.x = 3
>>> print A.x, B.x, C.x
3 2 3
What the $%#!&?? We only changed A.x
. Why did C.x
change too?x
is not found in class C
, it will be looked up in its base classes (only A
in the above example, although Python supports multiple inheritance). In other words, C
doesn’t have its own x
property, independent of A
. Thus, references to C.x
are in fact references to A.x
.>>> try:
... l = ["a", "b"]
... int(l[2])
... except ValueError, IndexError: # To catch both exceptions, right?
... pass
...
Traceback (most recent call last):
File "<stdin>", line 3, in <module>
IndexError: list index out of range
The problem here is that the except
statement does not take a list of exceptions specified in this manner. Rather, In Python 2.x, the syntax except Exception, e
is used to bind the exception to the optional second parameter specified (in this case e
), in order to make it available for further inspection. As a result, in the above code, the IndexError
exception is not being caught by the except
statement; rather, the exception instead ends up being bound to a parameter named IndexError
.except
statement is to specify the first parameter as a tuple containing all exceptions to be caught. Also, for maximum portability, use the as
keyword, since that syntax is supported by both Python 2 and Python 3:>>> try:
... l = ["a", "b"]
... int(l[2])
... except (ValueError, IndexError) as e:
... pass
...
>>>
>>> x = 10
>>> def foo():
... x += 1
... print x
...
>>> foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in foo
UnboundLocalError: local variable 'x' referenced before assignment
What’s the problem?UnboundLocalError
in previously working code when it is modified by adding an assignment
statement somewhere in the body of a function. (You can read more about
this here.)>>> lst = [1, 2, 3]
>>> def foo1():
... lst.append(5) # This works ok...
...
>>> foo1()
>>> lst
[1, 2, 3, 5]
>>> lst = [1, 2, 3]
>>> def foo2():
... lst += [5] # ... but this bombs!
...
>>> foo2()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in foo
UnboundLocalError: local variable 'lst' referenced before assignment
Huh? Why did foo2
bomb while foo1
ran fine?foo1
is not making an assignment to lst
, whereas foo2
is. Remembering that lst += [5]
is really just shorthand for lst = lst + [5]
, we see that we are attempting to assign a value to lst
(therefore presumed by Python to be in the local scope). However, the value we are looking to assign to lst
is based on lst
itself (again, now presumed to be in the local scope), which has not yet been defined. Boom.>>> odd = lambda x : bool(x % 2)
>>> numbers = [n for n in range(10)]
>>> for i in range(len(numbers)):
... if odd(numbers[i]):
... del numbers[i] # BAD: Deleting item from a list while iterating over it
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
IndexError: list index out of range
Deleting an item from a list or array while iterating over it is a
faux pas well known to any experienced software developer. But while
the example above may be fairly obvious, even advanced developers can be
unintentionally bitten by this in code that is much more complex.>>> odd = lambda x : bool(x % 2)
>>> numbers = [n for n in range(10)]
>>> numbers[:] = [n for n in numbers if not odd(n)] # ahh, the beauty of it all
>>> numbers
[0, 2, 4, 6, 8]
>>> def create_multipliers():
... return [lambda x : i * x for i in range(5)]
>>> for multiplier in create_multipliers():
... print multiplier(2)
...
You might expect the following output:0
2
4
6
8
But you actually get:8
8
8
8
8
Surprise!i
is looked up in the surrounding scope at the time it is called (and by then, the loop has completed, so i
has already been assigned its final value of 4).>>> def create_multipliers():
... return [lambda x, i=i : i * x for i in range(5)]
...
>>> for multiplier in create_multipliers():
... print multiplier(2)
...
0
2
4
6
8
Voilà! We are taking advantage of default arguments here to generate
anonymous functions in order to achieve the desired behavior. Some
would call this elegant. Some would call it subtle. Some hate it. But
if you’re a Python developer, it’s important to understand in any case.a.py
and b.py
, each of which imports the other, as follows:a.py
:import b
def f():
return b.x
print f()
And in b.py
:import a
x = 1
def g():
print a.f()
First, let’s try importing a.py
:>>> import a
1
Worked just fine. Perhaps that surprises you. After all, we do have
a circular import here which presumably should be a problem, shouldn’t
it?a.py
, it had no problem importing b.py
, since b.py
does not require anything from a.py
to be defined at the time it is imported. The only reference in b.py
to a
is the call to a.f()
. But that call is in g()
and nothing in a.py
or b.py
invokes g()
. So life is good.b.py
(without having previously imported a.py
, that is):>>> import b
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "b.py", line 1, in <module>
import a
File "a.py", line 6, in <module>
print f()
File "a.py", line 4, in f
return b.x
AttributeError: 'module' object has no attribute 'x'
Uh-oh. That’s not good! The problem here is that, in the process of importing b.py
, it attempts to import a.py
, which in turn calls f()
, which attempts to access b.x
. But b.x
has not yet been defined. Hence the AttributeError
exception. b.py
to import a.py
within g()
:x = 1
def g():
import a # This will be evaluated only when g() is called
print a.f()
No when we import it, everything is fine:>>> import b
>>> b.g()
1 # Printed a first time since module 'a' calls 'print f()' at the end
1 # Printed a second time, this one is our call to 'g'
email.py
in your code, which would be in conflict with the standard library module of the same name). foo.py
:import sys
def bar(i):
if i == 1:
raise KeyError(1)
if i == 2:
raise ValueError(2)
def bad():
e = None
try:
bar(int(sys.argv[1]))
except KeyError as e:
print('key error')
except ValueError as e:
print('value error')
print(e)
bad()
On Python 2, this runs fine:$ python foo.py 1
key error
1
$ python foo.py 2
value error
2
But now let’s give it a whirl on Python 3:$ python3 foo.py 1
key error
Traceback (most recent call last):
File "foo.py", line 19, in <module>
bad()
File "foo.py", line 17, in bad
print(e)
UnboundLocalError: local variable 'e' referenced before assignment
What has just happened here? The “problem” is that, in Python 3, the
exception object is not accessible beyond the scope of the except
block. (The reason for this is that, otherwise, it would keep a
reference cycle with the stack frame in memory until the garbage
collector runs and purges the references from memory. More technical
detail about this is available here).except
block so that it remains accessible. Here’s a version of the previous
example that uses this technique, thereby yielding code that is both
Python 2 and Python 3 friendly:import sys
def bar(i):
if i == 1:
raise KeyError(1)
if i == 2:
raise ValueError(2)
def good():
exception = None
try:
bar(int(sys.argv[1]))
except KeyError as e:
exception = e
print('key error')
except ValueError as e:
exception = e
print('value error')
print(exception)
good()
Running this on Py3k:$ python3 foo.py 1
key error
1
$ python3 foo.py 2
value error
2
Yippee!__del__
methodmod.py
:import foo
class Bar(object):
...
def __del__(self):
foo.cleanup(self.myhandle)
And you then tried to do this from another_mod.py
:import mod
mybar = mod.Bar()
You’d get an ugly AttributeError
exception.None
. As a result, in the above example, at the point that __del__
is invoked, the name foo
has already been set to None
.atexit.register()
instead. That way, when your program is finished executing (when
exiting normally, that is), your registered handlers are kicked off before the interpreter is shut down.mod.py
code might then look something like this:import foo
import atexit
def cleanup(handle):
foo.cleanup(handle)
class Bar(object):
def __init__(self):
...
atexit.register(cleanup, self.myhandle)
This implementation provides a clean and reliable way of calling any
needed cleanup functionality upon normal program termination.
Obviously, it’s up to foo.cleanup
to decide what to do with the object bound to the name self.myhandle
, but you get the idea.