Pysheeet KR Readthedocs Io Ko Latest
Pysheeet KR Readthedocs Io Ko Latest
0.1.0
crazyguitar
2018 03 03
Contents
i
1.36 Property - Managed attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1.37 Computed attributes - Using property . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.38 Descriptor - manage attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.39 @staticmethod, @classmethod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
1.40 Abstract method - Metaclass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
1.41 Common Use Magic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
1.42 Parsing csv string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
1.43 Using __slots__ to save memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
1.44 Using annotation for type hints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
1.45 Using annotation to check type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
ii
4.10 for _ in gen() simulate yield from . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
4.11 Check generator type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
4.12 Check Generator State . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
4.13 Simple compiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
4.14 Context manager and generator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
4.15 What @contextmanager actually doing? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
4.16 profile code block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
4.17 yield from and __iter__ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
4.18 yield from == await expression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
4.19 Closure in Python - using generator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
4.20 Implement a simple scheduler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
4.21 Simple round-robin with blocking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
4.22 simple round-robin with blocking and non-blocking . . . . . . . . . . . . . . . . . . . . . . . . . . 63
4.23 Asynchronous Generators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
4.24 Asynchronous generators can have try..finally blocks . . . . . . . . . . . . . . . . . . . . . . 65
4.25 send value and throw exception into async generator . . . . . . . . . . . . . . . . . . . . . . . . . . 65
4.26 Simple async round-robin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
4.27 Async generator get better performance than async iterator . . . . . . . . . . . . . . . . . . . . . . . 67
4.28 Asynchronous Comprehensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
iii
6.17 Simple Asynchronous TCP Server - Thread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
6.18 Simple Asynchronous TCP Server - select . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
6.19 Simple Asynchronous TCP Server - poll . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
6.20 Simple Asynchronous TCP Server - epoll . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
6.21 Simple Asynchronous TCP Server - kqueue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
6.22 High-Level API - selectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
6.23 Simple Non-blocking TLS/SSL socket via selectors . . . . . . . . . . . . . . . . . . . . . . . . . . 99
6.24 "socketpair" - Similar to PIPE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
6.25 Using sendfile do copy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
6.26 Sending a file through sendfile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
6.27 Linux kernel Crypto API - AF_ALG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
6.28 AES-CBC encrypt/decrypt via AF_ALG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
6.29 AES-GCM encrypt/decrypt via AF_ALG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
6.30 AES-GCM encrypt/decrypt file with sendfile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
6.31 Compare the performance of AF_ALG to cryptography . . . . . . . . . . . . . . . . . . . . . . . . 109
6.32 Sniffer IP packets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
6.33 Sniffer TCP packet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
6.34 Sniffer ARP packet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
iv
8.11 Ensure tasks has done . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
8.12 Thread-safe priority queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
8.13 Multiprocessing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
8.14 Custom multiprocessing map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
8.15 Graceful way to kill all child processes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
8.16 Simple round-robin scheduler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
8.17 Scheduler with blocking function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
8.18 PoolExecutor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
8.19 What "with ThreadPoolExecutor" doing? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
8.20 Future Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
8.21 Future error handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
v
10.7 Patch loop runner _run_once . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193
10.8 Put blocking task into Executor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
10.9 Socket with asyncio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
10.10 Event Loop with polling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
10.11 Transport and Protocol . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
10.12 Transport and Protocol with SSL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
10.13 What loop.create_server do? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
10.14 Inline callback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
10.15 Asynchronous Iterator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
10.16 What is asynchronous iterator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
10.17 Asynchronous context manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
10.18 What is asynchronous context manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
10.19 decorator @asynccontextmanager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
10.20 What loop.sock_* do? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
10.21 Simple asyncio connection pool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
10.22 Simple asyncio UDP echo server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
10.23 Simple asyncio web server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
10.24 Simple HTTPS asyncio web server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
10.25 Simple asyncio WSGI web server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
vi
13.4 Generator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249
13.5 Context Manager in C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250
13.6 Tuple in C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
13.7 Error Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
13.8 Simple try: exp except: exp finally: in C . . . . . . . . . . . . . . . . . . . . . . 253
13.9 Simple coroutine in C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254
13.10 Keyword Arguments in C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256
13.11 Function "MAP" . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
13.12 foreach in C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
13.13 Simple OOP in C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
vii
viii
CHAPTER 1
Table of Contents
1
python-cheatsheet Documentation, 0.1.0
– NamedTuple
– __iter__ - Delegating Iteration
– Using Generator as Iterator
– Emulating a list
– Emulating a dictionary
– Decorator
– Decorator with arguments
– for: exp else: exp
– try: exp else: exp
– Lambda function
– Option arguments - (*args, **kwargs)
– type() declare (create) a class
– Callable object
– Context Manager - with statement
– Using @contextmanager
– Using with statement open file
– Reading file chunk
– Property - Managed attributes
– Computed attributes - Using property
– Descriptor - manage attributes
– @staticmethod, @classmethod
– Abstract method - Metaclass
– Common Use Magic
– Parsing csv string
– Using __slots__ to save memory
– Using annotation for type hints
– Using annotation to check type
# see: PEP 8
# for class
#
# good:
# MyClass
# bad:
# myClass, my_class
(continues on next page)
( )
MyClass
( )
>>> 1/2
0
>>> from __future__ import division
>>> 1/2 # return a float (classic division)
0.5
>>> 1//2 # return a int (floor division)
0
: from __future__ import feature is a future statement. It use for backporting features of other python
version to current python version, not like original import.
>>> ex = 10
>>> isinstance(ex,int)
True
>>> a = 10
>>> def fun():
... print("I am callable")
...
>>> callable(a)
False
>>> callable(fun)
True
( )
# using brackets
>>> s = ("This is a very very very "
... "long python string")
>>> s
'This is a very very very long python string'
# using '+'
>>> s = ("This is a very very very " +
... "long python string")
>>> s
'This is a very very very long python string'
>>> a = [1, 2, 3, 4, 5]
>>> a[0]
1
>>> a[-1]
5
>>> a[0:]
[1, 2, 3, 4, 5]
>>> a[:-1]
[1, 2, 3, 4]
# a[start:end:step]
>>> a[0:-1:2]
[1, 3]
( )
# with filter
>>> [x for x in range(5) if x > 1]
[2, 3, 4]
>>> l = ['1', '2', 3, 'Hello', 4]
>>> predicate = lambda x: isinstance(x, int)
>>> filter(predicate, l)
[3, 4]
# reverse
>>> a = [1, 2, 3, 4, 5]
>>> a[::-1]
[5, 4, 3, 2, 1]
# be careful
>>> a = [[]] * 3
>>> b = [[] for _ in range(3)]
>>> a[0].append("Hello")
>>> a
[['Hello'], ['Hello'], ['Hello']]
>>> b[0].append("Python")
>>> b
[['Python'], [], []]
( )
# update dictionary
>>> a.update(b)
>>> a
{'1': 1, '3': 3, '2': 2, '4': 4}
# set comprehension
>>> a = [1, 2, 5, 6, 6, 6, 7]
>>> s = {x for x in a}
>>> s
set([1, 2, 5, 6, 7])
>>> s = {x for x in a if x > 3}
>>> s
set([5, 6, 7])
>>> s = {x if x > 3 else -1 for x in a}
>>> s
set([6, 5, -1, 7])
# uniquify list
>>> a = [1, 2, 2, 2, 3, 4, 5, 5]
>>> a
[1, 2, 2, 2, 3, 4, 5, 5]
>>> ua = list(set(a))
>>> ua
(continues on next page)
( )
[1, 2, 3, 4, 5]
# b contains a
>>> a = set([1, 2])
>>> b = set([1, 2, 5, 6])
>>> a <=b
True
# a contains b
>>> a = set([1, 2, 5, 6])
>>> b = set([1, 5, 6])
>>> a >= b
True
# set diff
>>> a = set([1, 2, 3])
>>> b = set([1, 5, 6, 7, 7])
>>> a - b
set([2, 3])
# symmetric diff
>>> a = set([1,2,3])
(continues on next page)
( )
>>> b = set([1, 5, 6, 7, 7])
>>> a ^ b
set([2, 3, 5, 6, 7])
1.19 NamedTuple
# namedtuple(typename, field_names)
# replace define class without method
>>> from collections import namedtuple
>>> Example = namedtuple("Example",'a b c')
>>> e = Example(1, 2, 3)
>>> print(e.a, e[1], e[1] + e.b)
1 2 4
# see: PEP289
>>> for x in g:
... print(x, end=' ')
... else:
... print()
...
0 1 2 3 4 5 6 7 8 9
# equivalent to
>>> def generator():
... for x in range(10):
... yield x
...
>>> g = generator()
(continues on next page)
( )
>>> for x in g:
... print(x, end=' ')
... else:
... print()
...
0 1 2 3 4 5 6 7 8 9
1.24 Decorator
# see: PEP318
>>> from functools import wraps
>>> def decorator(func):
... @wraps(func)
... def wrapper(*args, **kwargs):
... print("Before calling {}.".format(func.__name__))
... ret = func(*args, **kwargs)
... print("After calling {}.".format(func.__name__))
... return ret
... return wrapper
...
>>> @decorator
... def example():
(continues on next page)
( )
... print("Inside example function.")
...
>>> example()
Before calling example.
Inside example function.
After calling example.
# equivalent to
... def example():
... print("Inside example function.")
...
>>> example = decorator(example)
>>> example()
Before calling example.
Inside example function.
After calling example.
: @wraps preserve attributes of the original function, otherwise attributes of decorated function will be replaced by
wrapper function
# without @wraps
>>> def decorator(func):
... def wrapper(*args, **kwargs):
... print('wrap function')
... return func(*args, **kwargs)
... return wrapper
...
>>> @decorator
... def example(*a, **kw):
... pass
...
>>> example.__name__ # attr of function lose
'wrapper'
# with @wraps
>>> from functools import wraps
>>> def decorator(func):
... @wraps(func)
... def wrapper(*args, **kwargs):
... print('wrap function')
... return func(*args, **kwargs)
... return wrapper
...
>>> @decorator
... def example(*a, **kw):
... pass
...
>>> example.__name__ # attr of function preserve
'example'
1.24. Decorator 15
python-cheatsheet Documentation, 0.1.0
# equivalent to
>>> def example():
... print("This is example function.")
...
>>> example = decorator_with_argument(10)(example)
>>> example()
Val is 10
This is example function.
( )
... print("break occurred")
... break
...
... if flag == False:
... print("no break occurred")
...
break occurred
( )
>>> example(1, "var", 2, 3, word="hello")
1 var
(2, 3)
{'word': 'hello'}
>>> a_tuple = (1, 2, 3, 4, 5)
>>> a_dict = {"1":1, "2":2, "3":3}
>>> example(1, "var", *a_tuple, **a_dict)
1 var
(1, 2, 3, 4, 5)
{'1': 1, '2': 2, '3': 3}
# equal to
>>> class Fib(object):
... val = 10
... def fib(self, n):
... if n <=2:
... return 1
... return self.fib(n-1)+self.fib(n-2)
...
>>> f = Fib()
>>> f.val
10
>>> f.fib(f.val)
55
import socket
class Socket(object):
def __init__(self,host,port):
self.host = host
self.port = port
def __enter__(self):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((self.host,self.port))
sock.listen(5)
self.sock = sock
return self.sock
def __exit__(self,*exc_info):
if exc_info[0] is not None:
import traceback
traceback.print_exception(*exc_info)
self.sock.close()
if __name__=="__main__":
host = 'localhost'
port = 5566
with Socket(host, port) as s:
while True:
conn, addr = s.accept()
msg = conn.recv(1024)
print(msg)
conn.send(msg)
conn.close()
@contextmanager
def opening(filename, mode='r'):
f = open(filename, mode)
try:
yield f
finally:
f.close()
>>> chunk_size = 16
>>> content = ''
>>> with open('/etc/hosts') as f:
... for c in iter(lambda: f.read(chunk_size), ''):
... content += c
...
>>> print(content)
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
10.245.1.3 www.registry.io
# equivalent to
>>> class Example(object):
... def __init__(self, value):
... self._val = value
...
... def _val_getter(self):
(continues on next page)
( )
... return self._val
...
... def _val_setter(self, value):
... if not isintance(value, int):
... raise TypeError("Expected int")
... self._val = value
...
... def _val_deleter(self):
... del self._val
...
... val = property(fget=_val_getter, fset=_val_setter, fdel=_val_deleter,
˓→doc=None)
...
: @property compute the value of attribute only when we need. Not store in memory previously.
( )
>>> ex1 = Example(1)
>>> ex1.x
1
>>> ex2 = Example("str")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in __init__
File "<stdin>", line 11, in __set__
TypeError: Expected an int
>>> ex3 = Example(3)
>>> hasattr(ex3, 'x')
True
>>> del ex3.x
>>> hasattr(ex3, 'x')
False
( )
... __metaclass__ = ABCMeta
... @abstractmethod
... def absmethod(self):
... """ Abstract method """
...
>>> class example(base):
... def absmethod(self):
... print("abstract")
...
>>> ex = example()
>>> ex.absmethod()
abstract
# For Descriptor
__get__(self, instance, owner)
__set__(self, instance, value)
__delete__(self, instance)
( )
__getitem__(self, key)
__setitem__(self, key, value)
__delitem__(self, key)
__iter__(self)
__contains__(self, value)
# Callable object
__call__(self, [args...])
# Compare related
__cmp__(self, other)
__eq__(self, other)
__ne__(self, other)
__lt__(self, other)
__gt__(self, other)
__le__(self, other)
__ge__(self, other)
>>> try:
... from StringIO import StringIO # for py2
... except ImportError:
... from io import StringIO # for py3
...
>>> import csv
>>> s = "foo,bar,baz"
>>> f = StringIO(s)
>>> for x in csv.reader(f): print(x)
...
['foo', 'bar', 'baz']
# or
( )
>>> for x in csv.reader([s]): print(x)
...
['foo', 'bar', 'baz']
#!/usr/bin/env python3
import resource
import platform
import functools
def profile_mem(func):
@functools.wraps(func)
def wrapper(*a, **k):
s = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
ret = func(*a, **k)
e = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
uname = platform.system()
if uname == "Linux":
print(f"mem usage: {e - s} kByte")
elif uname == "Darwin":
print(f"mem usage: {e - s} Byte")
else:
raise Exception("not support")
return ret
return wrapper
class S(object):
__slots__ = ['attr1', 'attr2', 'attr3']
def __init__(self):
self.attr1 = "Foo"
self.attr2 = "Bar"
self.attr3 = "Baz"
class D(object):
def __init__(self):
self.attr1 = "Foo"
self.attr2 = "Bar"
self.attr3 = "Baz"
@profile_mem
def alloc(cls):
_ = [cls() for _ in range(1000000)]
alloc(S)
(continues on next page)
( )
alloc(D)
output:
$ python3.6 s.py
mem usage: 70922240 Byte
mem usage: 100659200 Byte
#!/usr/bin/env python3
class C(object):
pass
TC = TypeVar('C', bound=C)
( )
print("cls is Type? ", isinstance(cls, Type))
return cls()
import inspect
ANNO_EMPTY = inspect._empty
rtype = type(ret)
raise TypeError(f"type(ret) is '{anno}', not '{rtype}'")
def typechecked(func):
sig = inspect.signature(func)
@wraps(func)
def wrapper(*a, **k):
check_args(sig, *a, **k)
return check_ret(sig, func(*a, **k))
return wrapper
@typechecked
(continues on next page)
( )
def test1(a: int)->int:
return a
@typechecked
def test2(a: int):
return a
@typechecked
def test3(a)->str:
return a
@typechecked
def test4(a, b: str, c: str="c")->list:
return [a, b, c]
print(test1(9527))
print(test2(9487))
print(test3("Hello Python3"))
print(test4(9487, "bb", c="cc"))
try:
print(test3(9487))
except TypeError as e:
print(e)
try:
print(test4(5566, 9527))
except TypeError as e:
print(e)
try:
print(test4(123, "b", c=5566))
except TypeError as e:
print(e)
output:
9527
9487
Hello Python3
[9487, 'bb', 'cc']
type(ret) is '<class 'str'>', not '<class 'int'>'
type(b) is '<class 'str'>', not '<class 'int'>'
type(c) is '<class 'str'>', not '<class 'int'>'
Table of Contents
29
python-cheatsheet Documentation, 0.1.0
– Matrix multiplication
– Data Classes
– Built-in breakpoint()
Python 3
>>> print("print is a function")
print is a function
>>> print()
>>> for x in range(3):
... print(x, end=' ')
... else:
... print()
...
0 1 2
( )
>>> len([_c for _c in 'Café'])
5
Python 3
>>> s = 'Café'
>>> s
'Café'
>>> type(s)
<class 'str'>
>>> s.encode('utf-8')
b'Caf\xc3\xa9'
>>> s.encode('utf-8').decode('utf-8')
'Café'
>>> len([_c for _c in 'Café'])
4
Python 3
>>> class ParentCls(object):
... def foo(self):
... print("call parent")
...
>>> class ChildCls(ParentCls):
... def foo(self):
... super().foo()
... print("call child")
...
>>> p = ParentCls()
>>> c = ChildCls()
(continues on next page)
( )
>>> p.foo()
call parent
>>> c.foo()
call parent
call child
# equal to !=
>>> a != "Python3"
True
Python 3
>>> a != "Python2"
True
( )
... inf()
... print(o)
...
>>> outf()
change out
Python 3
( )
... for i in l:
... print(i)
...
>>> func([1,2,3])
1
2
3
2.13 fstring
>>> py = "Python3"
>>> f'Awesome {py}'
(continues on next page)
( )
'Awesome Python3'
>>> x = [1, 2, 3, 4, 5]
>>> f'{x}'
'[1, 2, 3, 4, 5]'
>>> def foo(x:int) -> int:
... return x + 1
...
>>> f'{foo(0)}'
'1'
>>> f'{123.567:1.3}'
'1.24e+02'
# debug
>>> try:
(continues on next page)
( )
... func()
... except ArithmeticError as e:
... print(e.__context__)
...
division by zero
# await in list
( )
... raise ValueError
... return sum([x*y for x, y in zip(self._arr, other._arr)])
... def __imatmul__(self, other):
... if not isinstance(other, Arr):
... raise TypeError
... if len(self) != len(other):
... raise ValueError
... res = sum([x*y for x, y in zip(self._arr, other._arr)])
... self._arr = [res]
... return self
... def __len__(self):
... return len(self._arr)
... def __str__(self):
... return self.__repr__()
... def __repr__(self):
... return "Arr({})".format(repr(self._arr))
...
>>> a = Arr(9, 5, 2, 7)
>>> b = Arr(5, 5, 6, 6)
>>> a @ b # __matmul__
124
>>> a @= b # __imatmul__
>>> a
Arr([124])
# immutable
( )
>>> try:
... d.x = "baz"
... except FrozenInstanceError as e:
... print(e)
...
cannot assign to field 'x'
>>> try:
... d.z = "baz"
... except FrozenInstanceError as e:
... print(e)
...
cannot assign to field 'z'
Table of Contents
>>> s = u'Café'
>>> type(s.encode('utf-8'))
<class 'bytes'>
43
python-cheatsheet Documentation, 0.1.0
>>> s = u'Café'
>>> for _c in s: print('U+%04x' % ord(_c))
...
U+0043
U+0061
U+0066
U+00e9
>>> u = ''
>>> for _c in u: print('U+%04x' % ord(_c))
...
U+4e2d
U+6587
>>> s = 'Café'
>>> type(s)
<class 'str'>
>>> s
'Café'
>>> s.encode('utf-8')
b'Caf\xc3\xa9'
>>> s.encode('utf-8').decode('utf-8')
'Café'
>>> s= 'Café'
>>> print [_c for _c in s]
['C', 'a', 'f', '\xc3', '\xa9']
>>> len(s)
5
>>> s = u'Café'
>>> print [_c for _c in s]
[u'C', u'a', u'f', u'\xe9']
>>> len(s)
4
>>> s = 'Café'
>>> print([_c for _c in s])
['C', 'a', 'f', 'é']
>>> len(s)
4
>>> bs = bytes(s, encoding='utf-8')
>>> print(bs)
b'Caf\xc3\xa9'
>>> len(bs)
5
# python 3
>>> u1 = 'Café' # unicode string
>>> u2 = 'Cafe\u0301'
>>> u1, u2
('Café', 'Cafe')
>>> len(u1), len(u2)
(4, 5)
>>> u1 == u2
False
>>> u1.encode('utf-8') # get u1 byte string
b'Caf\xc3\xa9'
>>> u2.encode('utf-8') # get u2 byte string
b'Cafe\xcc\x81'
>>> from unicodedata import normalize
>>> s1 = normalize('NFC', u1) # get u1 NFC format
>>> s2 = normalize('NFC', u2) # get u2 NFC format
>>> s1 == s2
True
>>> s1.encode('utf-8'), s2.encode('utf-8')
(b'Caf\xc3\xa9', b'Caf\xc3\xa9')
>>> s1 = normalize('NFD', u1) # get u1 NFD format
>>> s2 = normalize('NFD', u2) # get u2 NFD format
>>> s1, s2
(continues on next page)
( )
('Cafe', 'Cafe')
>>> s1 == s2
True
>>> s1.encode('utf-8'), s2.encode('utf-8')
(b'Cafe\xcc\x81', b'Cafe\xcc\x81')
Table of Contents
47
python-cheatsheet Documentation, 0.1.0
# generator function
# generator
#
# calling the generator function returns a generator
>>> g = gen_func()
>>> g
<generator object gen_func at 0x101238fd>
>>> next(g)
5566
>>> next(g)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
# generator expression
#
# generator expression evaluating directly to a generator
( )
StopIteration
# PEP 448
( )
>>> {*g}
{5, 6}
# unpacking to variables
( )
... print("Message:", msg)
...
>>> try:
... g = spam()
... # start generator
... next(g)
... # send message to generator
... g.send("Hello World!")
... except StopIteration:
... pass
...
Message: Hello World!
( )
...
>>> a = list(chain())
>>> a
['a', 'b', 0, 1, 2]
# equivalent to
# ref: pep380
>>> def subgen():
... for x in range(3):
... yield x
...
>>> EXP = subgen()
>>> def delegating_gen():
... _i = iter(EXP)
... try:
... _y = next(_i)
... except StopIteration as _e:
... RES = _e.value
... else:
... while True:
... _s = yield _y
... try:
... _y = _i.send(_s)
... except StopIteration as _e:
... RES = _e.value
... break
...
>>> g = delegating_gen()
>>> next(g)
0
>>> next(g)
1
>>> next(g)
2
# equivalent to
>>> EXP = subgen()
>>> def delegating_gen():
... RES = yield from EXP
...
>>> g = delegating_gen()
>>> next(g)
0
(continues on next page)
( )
>>> next(g)
1
# equal to
( )
'GEN_CREATED'
>>> next(g)
9527
>>> inspect.getgeneratorstate(g)
'GEN_SUSPENDED'
>>> g.close()
>>> inspect.getgeneratorstate(g)
'GEN_CLOSED'
import re
import types
from collections import namedtuple
tokens = [
r'(?P<NUMBER>\d+)',
r'(?P<PLUS>\+)',
r'(?P<MINUS>-)',
r'(?P<TIMES>\*)',
r'(?P<DIVIDE>/)',
r'(?P<WS>\s+)']
def tokenize(text):
scan = lex.scanner(text)
gen = (Token(m.lastgroup, m.group())
for m in iter(scan.match, None) if m.lastgroup != 'WS')
return gen
class Node:
_fields = []
def __init__(self, *args):
for attr, value in zip(self._fields, args):
setattr(self, attr, value)
class Number(Node):
_fields = ['value']
class BinOp(Node):
_fields = ['op', 'left', 'right']
def parse(toks):
lookahead, current = next(toks, None), None
def accept(*toktypes):
nonlocal lookahead, current
if lookahead and lookahead.type in toktypes:
current, lookahead = lookahead, next(toks, None)
(continues on next page)
( )
return True
def expr():
left = term()
while accept('PLUS', 'MINUS'):
left = BinOp(current.value, left)
left.right = term()
return left
def term():
left = factor()
while accept('TIMES', 'DIVIDE'):
left = BinOp(current.value, left)
left.right = factor()
return left
def factor():
if accept('NUMBER'):
return Number(int(current.value))
else:
raise SyntaxError()
return expr()
class NodeVisitor:
def visit(self, node):
stack = [self.genvisit(node)]
ret = None
while stack:
try:
node = stack[-1].send(ret)
stack.append(self.genvisit(node))
ret = None
except StopIteration as e:
stack.pop()
ret = e.value
return ret
class Evaluator(NodeVisitor):
def visit_Number(self, node):
return node.value
( )
elif node.op == '/':
return leftval / rightval
def evaluate(exp):
toks = tokenize(exp)
tree = parse(toks)
return Evaluator().visit(tree)
output:
python3 compiler.py
8.5
49995000
class GeneratorCM(object):
def __init__(self,gen):
self._gen = gen
def __enter__(self):
return next(self._gen)
( )
try:
if exc_info[0] is None:
next(self._gen)
else:
self._gen.throw(*exc_info)
raise RuntimeError
except StopIteration:
return True
except:
raise
# define a decorator
def contextmanager(func):
def run(*a, **k):
return GeneratorCM(func(*a, **k))
return run
with mylist() as l:
print l
output:
$ python ctx.py
[1, 2, 3, 4, 5]
exit scope
( )
...
block2 cost time: 3.00104284286
( )
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)
sock.setblocking(False)
sock.bind((host, port))
sock.listen(10)
@asyncio.coroutine
def echo_server():
while True:
conn, addr = yield from loop.sock_accept(sock)
loop.create_task(handler(conn))
@asyncio.coroutine
def handler(conn):
while True:
msg = yield from loop.sock_recv(conn, 1024)
if not msg:
break
yield from loop.sock_sendall(conn, msg)
conn.close()
# equal to
async def echo_server():
while True:
conn, addr = await loop.sock_accept(sock)
loop.create_task(handler(conn))
loop.create_task(echo_server())
loop.run_forever()
output: (bash 1)
$ nc localhost 5566
Hello
Hello
output: (bash 2)
$ nc localhost 5566
World
World
# nonlocal version
>>> def closure():
... x = 5566
(continues on next page)
( )
... def inner_func():
... nonlocal x
... x += 1
... return x
... return inner_func
...
>>> c = closure()
>>> c()
5567
>>> c()
5568
>>> c()
5569
# class version
>>> class Closure:
... def __init__(self):
... self._x = 5566
... def __call__(self):
... self._x += 1
... return self._x
...
>>> c = Closure()
>>> c()
5567
>>> c()
5568
>>> c()
5569
( )
... for x in range(1, n + 1):
... yield fib(x)
...
>>> from collections import deque
>>> t = [g_fib(3), g_fib(5)]
>>> q = deque()
>>> q.extend(t)
>>> def run():
... while q:
... try:
... t = q.popleft()
... print(next(t))
... q.append(t)
... except StopIteration:
... print("Task done")
...
>>> run()
1
1
1
1
2
2
Task done
3
5
Task done
tasks = deque()
w_read = {}
w_send = {}
def run():
while any([tasks, w_read, w_send]):
while not tasks:
# polling tasks
can_r, can_s,_ = select(w_read, w_send, [])
for _r in can_r:
tasks.append(w_read.pop(_r))
for _w in can_s:
tasks.append(w_send.pop(_w))
try:
task = tasks.popleft()
why,what = next(task)
if why == 'recv':
(continues on next page)
( )
w_read[what] = task
elif why == 'send':
w_send[what] = task
else:
raise RuntimeError
except StopIteration:
pass
def server():
host = ('localhost',5566)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(host)
sock.listen(5)
while True:
# tell scheduler want block
yield 'recv', sock
conn,addr = sock.accept()
tasks.append(client_handler(conn))
def client_handler(conn):
while True:
# tell scheduler want block
yield 'recv', conn
msg = conn.recv(1024)
if not msg:
break
# tell scheduler want block
yield 'send', conn
conn.send(msg)
conn.close()
tasks.append(server())
run()
tasks = deque()
w_read = {}
w_send = {}
def run():
while any([tasks, w_read, w_send]):
while not tasks:
# polling tasks
can_r,can_s,_ = select(w_read, w_send,[])
for _r in can_r:
tasks.append(w_read.pop(_r))
for _w in can_s:
(continues on next page)
( )
tasks.append(w_send.pop(_w))
try:
task = tasks.popleft()
why,what = next(task)
if why == 'recv':
w_read[what] = task
elif why == 'send':
w_send[what] = task
elif why == 'continue':
print what
tasks.append(task)
else:
raise RuntimeError
except StopIteration:
pass
def fib(n):
if n <= 2:
return 1
return fib(n-1) + fib(n-2)
def g_fib(n):
for x in range(1, n + 1):
yield 'continue', fib(x)
tasks.append(g_fib(15))
def server():
host = ('localhost',5566)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(host)
sock.listen(5)
while True:
yield 'recv', sock
conn,addr = sock.accept()
tasks.append(client_handler(conn))
def client_handler(conn):
while True:
yield 'recv', conn
msg = conn.recv(1024)
if not msg:
break
yield 'send', conn
conn.send(msg)
conn.close()
tasks.append(server())
run()
# PEP 525
#
# Need python-3.6 or above
( )
>>> async def agen(n, t=0.1):
... try:
... for x in range(n):
... await asyncio.sleep(t)
... val = yield x
... print(f'get val: {val}')
... except RuntimeError as e:
... await asyncio.sleep(t)
... yield repr(e)
...
>>> async def main(n):
... g = agen(n)
... ret = await g.asend(None) + await g.asend('foo')
... print(ret)
... ret = await g.athrow(RuntimeError('Get RuntimeError'))
... print(ret)
...
>>> loop = asyncio.get_event_loop()
>>> loop.run_until_complete(main(5))
get val: foo
1
RuntimeError('Get RuntimeError',)
# PEP 530
#
# Need python-3.6 or above
( )
... print(*ret)
... ret = [x async for x in agen(5, 0.1) if x < 3]
... print(*ret)
... ret = [x if x < 3 else -1 async for x in agen(5, 0.1)]
... print(*ret)
... ret = {f'{x}': x async for x in agen(5, 0.1)}
... print(ret)
>>> loop.run_until_complete(main())
0 1 2 3 4
0 1 2
0 1 2 -1 -1
{'0': 0, '1': 1, '2': 2, '3': 3, '4': 4}
# await in Comprehensions
( )
... print(ret)
... ret = {await f(0.1) async for f in gen(foo, bar) if await baz(1)}
... print(ret)
... ret = {f.__name__: await f(0.1) async for f in gen(foo, bar) if await baz(1)}
...
>>> import asyncio
>>> asyncio.get_event_loop()
>>> loop.run_until_complete(await_simple_task())
['foo', 'bar']
{'bar', 'foo'}
{'foo': 'foo', 'bar': 'bar'}
>>> loop.run_until_complete(await_other_task())
['foo', 'bar']
{'bar', 'foo'}
{'foo': 'foo', 'bar': 'bar'}
>>> loop.run_until_complete(await_gen_task())
['foo', 'bar']
{'bar', 'foo'}
{'foo': 'foo', 'bar': 'bar'}
['foo', 'bar']
{'bar', 'foo'}
{'foo': 'foo', 'bar': 'bar'}
Table of Contents
71
python-cheatsheet Documentation, 0.1.0
# open tag
>>> re.search('<[^/>][^>]*>', '<table>') != None
True
>>> re.search('<[^/>][^>]*>', '<a href="#label">') != None
True
>>> re.search('<[^/>][^>]*>', '<img src="/img">') != None
True
>>> re.search('<[^/>][^>]*>', '</table>') != None
False
# close tag
>>> re.search('</[^>]+>', '</table>') != None
True
# self close
>>> re.search('<[^/>]+/>', '<br />') != None
True
# Nesting groups
>>> m = re.search(r'(((\d{4})-\d{2})-\d{2})', '2016-01-01')
>>> m.groups()
('2016-01-01', '2016-01', '2016')
>>> m.group()
'2016-01-01'
>>> m.group(1)
'2016-01-01'
>>> m.group(2)
'2016-01'
>>> m.group(3)
'2016'
# capturing group
>>> m = re.search('(http|ftp)://([^/\r\n]+)(/[^\r\n]*)?', url)
>>> m.groups()
('http', 'stackoverflow.com', '/')
( )
False
# basic substitute
>>> res = "1a2b3c"
>>> re.sub(r'[a-z]',' ', res)
'1 2 3 '
# camelcase to underscore
>>> def convert(s):
... res = re.sub(r'(.)([A-Z][a-z]+)',r'\1_\2', s)
... return re.sub(r'([a-z])([A-Z])',r'\1_\2', res).lower()
...
>>> convert('CamelCase')
'camel_case'
>>> convert('CamelCamelCase')
'camel_camel_case'
>>> convert('SimpleHTTPServer')
'simple_http_server'
# basic
>>> re.sub('(?=\d{3})', ' ', '12345')
' 1 2 345'
>>> re.sub('(?!\d{3})', ' ', '12345')
'123 4 5 '
>>> re.sub('(?<=\d{3})', ' ', '12345')
'123 4 5 '
>>> re.sub('(?<!\d{3})', ' ', '12345')
' 1 2 345'
>>> re.match('^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$',
... '[email protected]')
<_sre.SRE_Match object at 0x1087a4d40>
# or
notation description
(?:...) Don’t capture group
25[0-5] Match 251-255 pattern
2[0-4][0-9] Match 200-249 pattern
[1]?[0-9][0-9] Match 0-199 pattern
( )
>>> mac
'3c:38:51:05:03:1e'
>>> exp = re.compile(r'''[0-9a-f]{2}([:])
... [0-9a-f]{2}
... (\1[0-9a-f]{2}){4}$''', re.X)
>>> exp.match(mac) is not None
True
5.15 Lexer
>>> import re
>>> from collections import namedtuple
>>> tokens = [r'(?P<NUMBER>\d+)',
... r'(?P<PLUS>\+)',
... r'(?P<MINUS>-)',
... r'(?P<TIMES>\*)',
... r'(?P<DIVIDE>/)',
... r'(?P<WS>\s+)']
>>> lex = re.compile('|'.join(tokens))
>>> Token = namedtuple('Token', ['type', 'value'])
>>> def tokenize(text):
... scan = lex.scanner(text)
... return (Token(m.lastgroup, m.group())
... for m in iter(scan.match, None) if m.lastgroup != 'WS')
...
>>> for _t in tokenize('9 + 5 * 2 - 7'):
... print(_t)
...
Token(type='NUMBER', value='9')
Token(type='PLUS', value='+')
Token(type='NUMBER', value='5')
Token(type='TIMES', value='*')
Token(type='NUMBER', value='2')
Token(type='MINUS', value='-')
Token(type='NUMBER', value='7')
5.15. Lexer 77
python-cheatsheet Documentation, 0.1.0
Table of Contents
79
python-cheatsheet Documentation, 0.1.0
# little-endian machine
>>> import socket
>>> a = 1 # host endian
>>> socket.htons(a) # network endian
256
>>> socket.htonl(a) # network endian
16777216
>>> socket.ntohs(256) # host endian
1
>>> socket.ntohl(16777216) # host endian
1
( )
# big-endian machine
>>> import socket
>>> a = 1 # host endian
>>> socket.htons(a) # network endian
1
>>> socket.htonl(a) # network endian
1L
>>> socket.ntohs(1) # host endian
1
>>> socket.ntohl(1) # host endian
1L
import socket
class Server(object):
def __init__(self,host,port):
self._host = host
self._port = port
def __enter__(self):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)
sock.bind((self._host,self._port))
sock.listen(10)
self._sock = sock
return self._sock
def __exit__(self,*exc_info):
if exc_info[0]:
import traceback
(continues on next page)
( )
traceback.print_exception(*exc_info)
self._sock.close()
if __name__ == '__main__':
host = 'localhost'
port = 5566
with Server(host,5566) as s:
while True:
conn, addr = s.accept()
msg = conn.recv(1024)
conn.send(msg)
conn.close()
output:
$ nc localhost 5566
Hello World
Hello World
import contextlib
import socket
host = "::1"
port = 5566
@contextlib.contextmanager
def server(host, port):
s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM, 0)
try:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host, port))
s.listen(10)
yield s
finally:
s.close()
if msg:
conn.send(msg)
conn.close()
except KeyboardInterrupt:
pass
output:
#!/usr/bin/env python3
import contextlib
import socket
host = "::"
port = 5566
@contextlib.contextmanager
def server(host: str, port: int):
s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM, 0)
try:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
s.bind((host, port))
s.listen(10)
yield s
finally:
s.close()
if msg:
conn.send(msg)
conn.close()
except KeyboardInterrupt:
pass
output:
$ python3 ipv6.py
[1] 23914
$ nc -4 127.0.0.1 5566
('::ffff:127.0.0.1', 42604, 0, 0)
Hello IPv4
Hello IPv4
$ nc -6 ::1 5566
('::1', 50882, 0, 0)
Hello IPv6
(continues on next page)
( )
Hello IPv6
$ nc -6 fe80::a00:27ff:fe9b:50ee%enp0s3 5566
('fe80::a00:27ff:fe9b:50ee%enp0s3', 42042, 0, 2)
Hello IPv6
Hello IPv6
output:
$ nc localhost 5566
Hello World
Hello World
import socket
import ssl
sslctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
sslctx.load_cert_chain(certfile='./root-ca.crt',
keyfile='./root-ca.key')
try:
while True:
conn, addr = sock.accept()
sslconn = sslctx.wrap_socket(conn, server_side=True)
msg = sslconn.recv(1024)
if msg:
sslconn.send(msg)
sslconn.close()
finally:
sock.close()
output:
# console 1
$ openssl genrsa -out root-ca.key 2048
$ openssl req -x509 -new -nodes -key root-ca.key -days 365 -out root-ca.crt
$ python3 ssl_tcp_server.py
# console 2
$ openssl s_client -connect localhost:5566
...
Hello SSL
Hello SSL
read:errno=0
import socket
import json
import ssl
sslctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
sslctx.load_cert_chain(certfile='cert.pem',
keyfile='key.pem')
# set ssl ciphers
sslctx.set_ciphers('ECDH-ECDSA-AES128-GCM-SHA256')
print(json.dumps(sslctx.get_ciphers(), indent=2))
try:
while True:
conn, addr = sock.accept()
sslconn = sslctx.wrap_socket(conn, server_side=True)
msg = sslconn.recv(1024)
if msg:
sslconn.send(msg)
sslconn.close()
finally:
sock.close()
output:
$ openssl ecparam -out key.pem -genkey -name prime256v1
$ openssl req -x509 -new -key key.pem -out cert.pem
$ python3 tls.py&
[2] 64565
[
{
"id": 50380845,
"name": "ECDH-ECDSA-AES128-GCM-SHA256",
"protocol": "TLSv1/SSLv3",
"description": "ECDH-ECDSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH/ECDSA Au=ECDH
˓→Enc=AESGCM(128) Mac=AEAD",
(continues on next page)
( )
"strength_bits": 128,
"alg_bits": 128
}
]
$ openssl s_client -connect localhost:5566 -cipher "ECDH-ECDSA-AES128-GCM-SHA256"
...
---
Hello ECDH-ECDSA-AES128-GCM-SHA256
Hello ECDH-ECDSA-AES128-GCM-SHA256
read:errno=0
import socket
class UDPServer(object):
def __init__(self,host,port):
self._host = host
self._port = port
def __enter__(self):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((self._host,self._port))
self._sock = sock
return sock
def __exit__(self,*exc_info):
if exc_info[0]:
import traceback
traceback.print_exception(*exc_info)
self._sock.close()
if __name__ == '__main__':
host = 'localhost'
port = 5566
with UDPServer(host,port) as s:
while True:
msg, addr = s.recvfrom(1024)
s.sendto(msg, addr)
output:
$ nc -u localhost 5566
Hello World
Hello World
( )
... m,s = self.request
... s.sendto(m,self.client_address)
... print(self.client_address)
...
>>> host = ('localhost',5566)
>>> s = SocketServer.UDPServer(
... host, handler)
>>> s.serve_forever()
output:
$ nc -u localhost 5566
Hello World
Hello World
output:
output:
$ nc -k -w 1 -ul 5566
1431473025.72
import socket
import contextlib
import os
@contextlib.contextmanager
def DomainServer(addr):
try:
if os.path.exists(addr):
os.unlink(addr)
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.bind(addr)
sock.listen(10)
yield sock
finally:
sock.close()
if os.path.exists(addr):
os.unlink(addr)
addr = "./domain.sock"
with DomainServer(addr) as sock:
while True:
conn, _ = sock.accept()
msg = conn.recv(1024)
conn.send(msg)
conn.close()
output:
$ nc -U ./domain.sock
Hello
Hello
import os
import socket
if pid == 0:
print('chlid pid: {}'.format(os.getpid()))
child.send(b'Hello Parent')
msg = child.recv(1024)
print('p[{}] ---> c[{}]: {}'.format(
os.getppid(), os.getpid(), msg))
else:
print('parent pid: {}'.format(os.getpid()))
( )
msg = parent.recv(1024)
print('c[{}] ---> p[{}]: {}'.format(
pid, os.getpid(), msg))
parent.send(msg)
except KeyboardInterrupt:
pass
finally:
child.close()
parent.close()
output:
$ python3 socketpair_demo.py
parent pid: 9497
chlid pid: 9498
c[9498] ---> p[9497]: b'Hello Parent'
p[9497] ---> c[9498]: b'Hello Parent'
output: (bash 1)
$ nc localhost 5566
Hello
Hello
output: (bash 2)
$ nc localhost 5566
Ker Ker
Ker Ker
host = ('localhost',5566)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)
sock.bind(host)
sock.listen(5)
rl = [sock]
wl = []
ml = {}
try:
while True:
r, w, _ = select(rl,wl,[])
# process ready to ready
for _ in r:
if _ == sock:
conn, addr = sock.accept()
rl.append(conn)
else:
msg = _.recv(1024)
ml[_.fileno()] = msg
wl.append(_)
# process ready to write
for _ in w:
msg = ml[_.fileno()]
_.send(msg)
wl.remove(_)
del ml[_.fileno()]
except:
sock.close()
output: (bash 1)
$ nc localhost 5566
Hello
Hello
output: (bash 2)
$ nc localhost 5566
Ker Ker
Ker Ker
import socket
import select
import contextlib
( )
host = 'localhost'
port = 5566
con = {}
req = {}
resp = {}
@contextlib.contextmanager
def Server(host,port):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.setblocking(False)
s.bind((host,port))
s.listen(10)
yield s
except socket.error:
print("Get socket error")
raise
finally:
if s: s.close()
@contextlib.contextmanager
def Poll():
try:
e = select.poll()
yield e
finally:
for fd, c in con.items():
e.unregister(fd)
c.close()
conn = req[fd]
msg = conn.recv(1024)
if msg:
resp[fd] = msg
poll.modify(fd, select.POLLOUT)
else:
conn.close()
del con[fd]
del req[fd]
(continues on next page)
( )
conn = con[fd]
msg = resp[fd]
b = 0
total = len(msg)
while total > b:
l = conn.send(msg)
msg = msg[l:]
b += l
del resp[fd]
req[fd] = conn
poll.modify(fd, select.POLLIN)
try:
with Server(host, port) as server, Poll() as poll:
poll.register(server.fileno())
while True:
events = poll.poll(1)
for fd, e in events:
if fd == server.fileno():
accept(server, poll)
elif e & (select.POLLIN | select.POLLPRI):
recv(fd, poll)
elif e & select.POLLOUT:
send(fd, poll)
except KeyboardInterrupt:
pass
output: (bash 1)
output: (bash 2)
$ nc localhost 5566
Hello Python
Hello Python
Hello Awesome Python
Hello Awesome Python
import socket
import select
import contextlib
host = 'localhost'
port = 5566
con = {}
req = {}
resp = {}
@contextlib.contextmanager
def Server(host,port):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.setblocking(False)
s.bind((host,port))
s.listen(10)
yield s
except socket.error:
print("Get socket error")
raise
finally:
if s: s.close()
@contextlib.contextmanager
def Epoll():
try:
e = select.epoll()
yield e
finally:
for fd in con: e.unregister(fd)
e.close()
conn = req[fd]
msg = conn.recv(1024)
(continues on next page)
( )
if msg:
resp[fd] = msg
epoll.modify(fd, select.EPOLLOUT)
else:
conn.close()
del con[fd]
del req[fd]
conn = con[fd]
msg = resp[fd]
b = 0
total = len(msg)
while total > b:
l = conn.send(msg)
msg = msg[l:]
b += l
del resp[fd]
req[fd] = conn
epoll.modify(fd, select.EPOLLIN)
try:
with Server(host, port) as server, Epoll() as epoll:
epoll.register(server.fileno())
while True:
events = epoll.poll(1)
for fd, e in events:
if fd == server.fileno():
accept(server, epoll)
elif e & select.EPOLLIN:
recv(fd, epoll)
elif e & select.EPOLLOUT:
send(fd, epoll)
except KeyboardInterrupt:
pass
output: (bash 1)
output: (bash 2)
$ nc localhost 5566
Hello Python
Hello Python
Hello Awesome Python
Hello Awesome Python
import socket
import select
import contextlib
host = 'localhost'
port = 5566
con = {}
req = {}
resp = {}
@contextlib.contextmanager
def Server(host,port):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.setblocking(False)
s.bind((host,port))
s.listen(10)
yield s
except socket.error:
print("Get socket error")
raise
finally:
if s: s.close()
@contextlib.contextmanager
def Kqueue():
try:
kq = select.kqueue()
yield kq
finally:
kq.close()
for fd, c in con.items(): c.close()
( )
fd = conn.fileno()
ke = select.kevent(conn.fileno(),
select.KQ_FILTER_READ,
select.KQ_EV_ADD)
kq.control([ke], 0)
req[fd] = conn
con[fd] = conn
conn = req[fd]
msg = conn.recv(1024)
if msg:
resp[fd] = msg
# remove read event
ke = select.kevent(fd,
select.KQ_FILTER_READ,
select.KQ_EV_DELETE)
kq.control([ke], 0)
# add write event
ke = select.kevent(fd,
select.KQ_FILTER_WRITE,
select.KQ_EV_ADD)
kq.control([ke], 0)
req[fd] = conn
con[fd] = conn
else:
conn.close()
del con[fd]
del req[fd]
conn = con[fd]
msg = resp[fd]
b = 0
total = len(msg)
while total > b:
l = conn.send(msg)
msg = msg[l:]
b += l
del resp[fd]
req[fd] = conn
# remove write event
ke = select.kevent(fd,
select.KQ_FILTER_WRITE,
select.KQ_EV_DELETE)
kq.control([ke], 0)
# add read event
(continues on next page)
( )
ke = select.kevent(fd,
select.KQ_FILTER_READ,
select.KQ_EV_ADD)
kq.control([ke], 0)
try:
with Server(host, port) as server, Kqueue() as kq:
max_events = 1024
timeout = 1
ke = select.kevent(server.fileno(),
select.KQ_FILTER_READ,
select.KQ_EV_ADD)
kq.control([ke], 0)
while True:
events = kq.control(None, max_events, timeout)
for e in events:
fd = e.ident
if fd == server.fileno():
accept(server, kq)
elif e.filter == select.KQ_FILTER_READ:
recv(fd, kq)
elif e.filter == select.KQ_FILTER_WRITE:
send(fd, kq)
except KeyboardInterrupt:
pass
output: (bash 1)
$ python3 kqueue.py &
[1] 3036
$ nc localhost 5566
Hello kqueue
Hello kqueue
Hello Python Socket Programming
Hello Python Socket Programming
output: (bash 2)
$ nc localhost 5566
Hello Python
Hello Python
Hello Awesome Python
Hello Awesome Python
# Pyton3.4+ only
# Reference: selectors
import selectors
import socket
(continues on next page)
( )
import contextlib
@contextlib.contextmanager
def Server(host,port):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host,port))
s.listen(10)
sel = selectors.DefaultSelector()
yield s, sel
except socket.error:
print("Get socket error")
raise
finally:
if s:
s.close()
host = 'localhost'
port = 5566
with Server(host, port) as (s,sel):
sel.register(s, selectors.EVENT_READ, accept_handler)
while True:
events = sel.select()
for sel_key, m in events:
handler = sel_key.data
handler(sel_key.fileobj, sel)
output: (bash 1)
$ nc localhost 5566
Hello
Hello
output: (bash 1)
$ nc localhost 5566
Hi
Hi
import socket
import selectors
import contextlib
import ssl
sslctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
sslctx.load_cert_chain(certfile="cert.pem", keyfile="key.pem")
@contextlib.contextmanager
def Server(host,port):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host,port))
s.listen(10)
sel = selectors.DefaultSelector()
yield s, sel
except socket.error:
print("Get socket error")
raise
finally:
if s: s.close()
if sel: sel.close()
( )
host = 'localhost'
port = 5566
try:
with Server(host, port) as (s,sel):
sel.register(s, selectors.EVENT_READ, accept)
while True:
events = sel.select()
for sel_key, m in events:
handler = sel_key.data
handler(sel_key.fileobj, sel)
except KeyboardInterrupt:
pass
output:
# console 1
$ openssl genrsa -out key.pem 2048
$ openssl req -x509 -new -nodes -key key.pem -days 365 -out cert.pem
$ python3 ssl_tcp_server.py &
$ openssl s_client -connect localhost:5566
...
---
Hello TLS
Hello TLS
# console 2
$ openssl s_client -connect localhost:5566
...
---
Hello SSL
Hello SSL
import socket
import os
import time
if pid:
# parent process
c_s.close()
while True:
p_s.sendall("Hi! Child!")
msg = p_s.recv(1024)
print(msg)
(continues on next page)
( )
time.sleep(3)
os.wait()
else:
# child process
p_s.close()
while True:
msg = c_s.recv(1024)
print(msg)
c_s.sendall("Hi! Parent!")
output:
$ python ex.py
Hi! Child!
Hi! Parent!
Hi! Child!
Hi! Parent!
...
import os
import sys
if len(sys.argv) != 3:
print("Usage: cmd src dst")
exit(1)
src = sys.argv[1]
dst = sys.argv[2]
offset = 0
count = 4096
s_len = st.st_size
sfd = s.fileno()
dfd = d.fileno()
output:
$ dd if=/dev/urandom of=dd.in bs=1M count=1024
1024+0 records in
1024+0 records out
(continues on next page)
( )
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 108.02 s, 9.9 MB/s
$ python3 sendfile.py dd.in dd.out
$ md5sum dd.in
e79afdd6aba71b7174142c0bbc289674 dd.in
$ md5sum dd.out
e79afdd6aba71b7174142c0bbc289674 dd.out
import os
import sys
import time
import socket
import contextlib
@contextlib.contextmanager
def server(host, port):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host, port))
s.listen(10)
yield s
finally:
s.close()
@contextlib.contextmanager
def client(host, port):
try:
c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
c.connect((host, port))
yield c
finally:
c.close()
( )
fout.write(data)
host = 'localhost'
port = 5566
if len(sys.argv) != 3:
print("usage: cmd src dst")
exit(1)
src = sys.argv[1]
dst = sys.argv[2]
offset = 0
pid = os.fork()
if pid == 0:
# client
time.sleep(3)
with client(host, port) as c, open(src, 'rb') as f:
fd = f.fileno()
st = os.fstat(fd)
count = 4096
flen = st.st_size
do_sendfile(c, f, count, flen)
else:
# server
with server(host, port) as s, open(dst, 'wb') as f:
conn, addr = s.accept()
do_recv(f, conn)
output:
$ dd if=/dev/urandom of=dd.in bs=1M count=512
512+0 records in
512+0 records out
536870912 bytes (537 MB, 512 MiB) copied, 3.17787 s, 169 MB/s
$ python3 sendfile.py dd.in dd.out
$ md5sum dd.in
eadfd96c85976b1f46385e89dfd9c4a8 dd.in
$ md5sum dd.out
eadfd96c85976b1f46385e89dfd9c4a8 dd.out
@contextlib.contextmanager
(continues on next page)
( )
def create_alg(typ, name):
s = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0)
try:
s.bind((typ, name))
yield s
finally:
s.close()
# check data
h = hashlib.sha256(msg).digest()
if h != data:
raise Exception(f"sha256({h}) != af_alg({data})")
output:
$ python3 af_alg.py
9d50bcac2d5e33f936ec2db7dc7b6579cba8e1b099d77c31d8564df46f66bdf5
BS = 16 # Bytes
pad = lambda s: s + (BS - len(s) % BS) * \
chr(BS - len(s) % BS).encode('utf-8')
@contextlib.contextmanager
def create_alg(typ, name):
s = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0)
try:
s.bind((typ, name))
yield s
finally:
s.close()
( )
algo.setsockopt(socket.SOL_ALG, socket.ALG_SET_KEY, key)
op, _ = algo.accept()
with op:
plaintext = pad(plaintext)
op.sendmsg_afalg([plaintext],
op=socket.ALG_OP_ENCRYPT,
iv=iv)
ciphertext = op.recv(len(plaintext))
return ciphertext
return upad(plaintext)
key = os.urandom(32)
iv = os.urandom(16)
print(ciphertext.hex())
print(plaintext)
output:
$ python3 aes_cbc.py
01910e4bd6932674dba9bebd4fdf6cf2
b'Demo AF_ALG'
@contextlib.contextmanager
def create_alg(typ, name):
s = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0)
try:
s.bind((typ, name))
(continues on next page)
( )
yield s
finally:
s.close()
assoclen = len(assoc)
ciphertext = None
tag = None
op, _ = algo.accept()
with op:
msg = assoc + plaintext
op.sendmsg_afalg([msg],
op=socket.ALG_OP_ENCRYPT,
iv=iv,
assoclen=assoclen)
( )
algo.setsockopt(socket.SOL_ALG,
socket.ALG_SET_AEAD_AUTHSIZE,
None,
assoclen)
op, _ = algo.accept()
with op:
msg = assoc + ciphertext + tag
op.sendmsg_afalg([msg],
op=socket.ALG_OP_DECRYPT, iv=iv,
assoclen=assoclen)
taglen = len(tag)
res = op.recv(len(msg) - taglen)
plaintext = res[assoclen:]
return plaintext
key = os.urandom(16)
iv = os.urandom(12)
assoc = os.urandom(16)
print(ciphertext.hex())
print(plaintext)
output:
$ python3 aes_gcm.py
2e27b67234e01bcb0ab6b451f4f870ce
b'Hello AES-GCM'
@contextlib.contextmanager
def create_alg(typ, name):
s = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0)
try:
s.bind((typ, name))
yield s
finally:
s.close()
( )
ciphertext = None
tag = None
pfd = pfile.fileno()
offset = 0
st = os.fstat(pfd)
totalbytes = st.st_size
op, _ = algo.accept()
with op:
op.sendmsg_afalg(op=socket.ALG_OP_ENCRYPT,
iv=iv,
assoclen=assoclen,
flags=socket.MSG_MORE)
op.sendall(assoc, socket.MSG_MORE)
taglen = len(tag)
res = op.recv(len(msg) - taglen)
plaintext = res[assoclen:]
( )
return plaintext
key = os.urandom(16)
iv = os.urandom(12)
assoc = os.urandom(16)
if len(sys.argv) != 2:
print("usage: cmd plain")
exit(1)
plain = sys.argv[1]
print(ciphertext.hex())
print(plaintext)
output:
$ echo "Test AES-GCM with sendfile" > plain.txt
$ python3 aes_gcm.py plain.txt
b3800044520ed07fa7f20b29c2695bae9ab596065359db4f009dd6
b'Test AES-GCM with sendfile\n'
@contextlib.contextmanager
def create_alg(typ, name):
s = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0)
try:
s.bind((typ, name))
yield s
finally:
s.close()
pfd = pfile.fileno()
totalbytes = psize
(continues on next page)
( )
op.sendmsg_afalg(op=socket.ALG_OP_ENCRYPT,
iv=iv,
assoclen=assoclen,
flags=socket.MSG_MORE)
op.sendall(assoc, socket.MSG_MORE)
taglen = len(tag)
res = op.recv(len(msg) - taglen)
plaintext = res[assoclen:]
return plaintext
key = os.urandom(16)
iv = os.urandom(12)
assoc = os.urandom(16)
assoclen = len(assoc)
count = 1000000
plain = "tmp.rand"
enc_algo.setsockopt(socket.SOL_ALG,
socket.ALG_SET_KEY, key)
enc_algo.setsockopt(socket.SOL_ALG,
socket.ALG_SET_AEAD_AUTHSIZE,
(continues on next page)
( )
None,
assoclen)
dec_algo.setsockopt(socket.SOL_ALG,
socket.ALG_SET_KEY, key)
dec_algo.setsockopt(socket.SOL_ALG,
socket.ALG_SET_AEAD_AUTHSIZE,
None,
assoclen)
enc_op, _ = enc_algo.accept()
dec_op, _ = dec_algo.accept()
st = os.fstat(pf.fileno())
psize = st.st_size
s = time.time()
for _ in range(count):
ciphertext, tag = encrypt(key, iv, assoc, 16, enc_op, pf, psize)
plaintext = decrypt(key, iv, assoc, tag, dec_op, ciphertext)
cost = time.time() - s
aesgcm = AESGCM(key)
s = time.time()
for _ in range(count):
pf.seek(0, 0)
plaintext = pf.read()
ciphertext = aesgcm.encrypt(iv, plaintext, assoc)
plaintext = aesgcm.decrypt(iv, ciphertext, assoc)
cost = time.time() - s
# clean up
os.remove(plain)
output:
$ python3 aes-gcm.py
total cost time: 15.317010641098022. [AF_ALG]
total cost time: 50.256704807281494. [cryptography]
class IP(Structure):
''' IP header Structure
strcut ip {
u_char ip_hl:4; /* header_len */
u_char ip_v:4; /* version */
u_char ip_tos; /* type of service */
short ip_len; /* total len */
u_short ip_id; /* identification */
short ip_off; /* offset field */
u_char ip_ttl; /* time to live */
u_char ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src; /* source */
struct in_addr ip_dst; /* destination */
};
'''
_fields_ = [("ip_hl" , c_ubyte, 4), # 4 bit
("ip_v" , c_ubyte, 4), # 1 byte
("ip_tos", c_uint8), # 2 byte
("ip_len", c_uint16), # 4 byte
("ip_id" , c_uint16), # 6 byte
("ip_off", c_uint16), # 8 byte
("ip_ttl", c_uint8), # 9 byte
("ip_p" , c_uint8), # 10 byte
("ip_sum", c_uint16), # 12 byte
("ip_src", c_uint32), # 16 byte
("ip_dst", c_uint32)] # 20 byte
( )
host = '0.0.0.0'
s = socket.socket(socket.AF_INET,
socket.SOCK_RAW,
socket.IPPROTO_ICMP)
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
s.bind((host, 0))
print("Sniffer start...")
try:
while True:
buf = s.recvfrom(65535)[0]
ip_header = IP(buf[:20])
print('{0}: {1} -> {2}'.format(ip_header.proto,
ip_header.src,
ip_header.dst))
except KeyboardInterrupt:
s.close()
output: (bash 1)
python sniffer.py
Sniffer start...
ICMP: 127.0.0.1 -> 127.0.0.1
ICMP: 127.0.0.1 -> 127.0.0.1
ICMP: 127.0.0.1 -> 127.0.0.1
output: (bash 2)
$ ping -c 3 localhost
PING localhost (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.063 ms
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.087 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.159 ms
#!/usr/bin/env python3.6
"""
Based on RFC-793, the following figure shows the TCP header format:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
(continues on next page)
( )
| Data | |U|A|P|R|S|F| |
| Offset| Reserved |R|C|S|S|Y|I| Window |
| | |G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
struct tcphdr {
__be16 source;
__be16 dest;
__be32 seq;
__be32 ack_seq;
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u16 res1:4,
doff:4,
fin:1,
syn:1,
rst:1,
psh:1,
ack:1,
urg:1,
ece:1,
cwr:1;
#elif defined(__BIG_ENDIAN_BITFIELD)
__u16 doff:4,
res1:4,
cwr:1,
ece:1,
urg:1,
ack:1,
psh:1,
rst:1,
syn:1,
fin:1;
#else
#error "Adjust your <asm/byteorder.h> defines"
#endif
__be16 window;
__sum16 check;
__be16 urg_ptr;
};
"""
import sys
import socket
import platform
un = platform.system()
if un != "Linux":
(continues on next page)
( )
print(f"{un} is not supported!")
sys.exit(1)
@contextmanager
def create_socket():
''' Create a TCP raw socket '''
s = socket.socket(socket.AF_INET,
socket.SOCK_RAW,
socket.IPPROTO_TCP)
try:
yield s
finally:
s.close()
try:
with create_socket() as s:
while True:
pkt, addr = s.recvfrom(65535)
doff = dr >> 4
fin = flags & 0x01
syn = flags & 0x02
rst = flags & 0x04
psh = flags & 0x08
ack = flags & 0x10
urg = flags & 0x20
ece = flags & 0x40
cwr = flags & 0x80
tcplen = (doff) * 4
h_size = iplen + tcplen
if not data:
continue
( )
print(f"Destination Port: {dest}")
print(f"Sequence Number: {seq}")
print(f"Acknowledgment Number: {ack_seq}")
print(f"Data offset: {doff}")
print(f"FIN: {fin}")
print(f"SYN: {syn}")
print(f"RST: {rst}")
print(f"PSH: {psh}")
print(f"ACK: {ack}")
print(f"URG: {urg}")
print(f"ECE: {ece}")
print(f"CWR: {cwr}")
print(f"Window: {window}")
print(f"Checksum: {check}")
print(f"Urgent Point: {urg_ptr}")
print("--------------- DATA -----------------")
print(data)
except KeyboardInterrupt:
pass
output:
$ python3.6 tcp.py
------------ TCP_HEADER --------------
Source Port: 38352
Destination Port: 8000
Sequence Number: 2907801591
Acknowledgment Number: 398995857
Data offset: 8
FIN: 0
SYN: 0
RST: 0
PSH: 8
ACK: 16
URG: 0
ECE: 0
CWR: 0
Window: 342
Checksum: 65142
Urgent Point: 0
--------------- DATA -----------------
b'GET / HTTP/1.1\r\nHost: localhost:8000\r\nUser-Agent: curl/7.47.0\r\nAccept: */
˓→*\r\n\r\n'
"""
Ehternet Packet Header
struct ethhdr {
unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
unsigned char h_source[ETH_ALEN]; /* source ether addr */
__be16 h_proto; /* packet type ID field */
(continues on next page)
( )
} __attribute__((packed));
struct arphdr {
uint16_t htype; /* Hardware Type */
uint16_t ptype; /* Protocol Type */
u_char hlen; /* Hardware Address Length */
u_char plen; /* Protocol Address Length */
uint16_t opcode; /* Operation Code */
u_char sha[6]; /* Sender hardware address */
u_char spa[4]; /* Sender IP address */
u_char tha[6]; /* Target hardware address */
u_char tpa[4]; /* Target IP address */
};
"""
import socket
import struct
import binascii
rawSocket = socket.socket(socket.AF_PACKET,
socket.SOCK_RAW,
socket.htons(0x0003))
while True:
packet = rawSocket.recvfrom(2048)
ethhdr = packet[0][0:14]
eth = struct.unpack("!6s6s2s", ethhdr)
arphdr = packet[0][14:42]
arp = struct.unpack("2s2s1s1s2s6s4s6s4s", arphdr)
# skip non-ARP packets
ethtype = eth[2]
if ethtype != '\x08\x06': continue
output:
$ python arp.py
-------------- ETHERNET_FRAME -------------
(continues on next page)
( )
Dest MAC: ffffffffffff
Source MAC: f0257252f5ca
Type: 0806
--------------- ARP_HEADER ----------------
Hardware type: 0001
Protocol type: 0800
Hardware size: 06
Protocol size: 04
Opcode: 0001
Source MAC: f0257252f5ca
Source IP: 140.112.91.254
Dest MAC: 000000000000
Dest IP: 140.112.91.20
-------------------------------------------
Table of Contents
119
python-cheatsheet Documentation, 0.1.0
# python2
# python3
backend = default_backend()
with open('./cert.crt', 'rb') as f:
crt_data = f.read()
cert = x509.load_pem_x509_certificate(crt_data, backend)
class Certificate:
_fields = ['country_name',
'state_or_province_name',
'locality_name',
'organization_name',
(continues on next page)
( )
'organizational_unit_name',
'common_name',
'email_address']
cert = Certificate(cert)
for attr in cert._fields:
for info in getattr(cert, attr):
print("{}: {}".format(info._oid._name, info._value))
output:
now = datetime.now()
expire = now + timedelta(days=365)
# country (countryName, C)
# state or province name (stateOrProvinceName, ST)
# locality (locality, L)
# organization (organizationName, O)
# organizational unit (organizationalUnitName, OU)
# common name (commonName, CN)
cert = crypto.X509()
cert.get_subject().C = "TW"
cert.get_subject().ST = "Taiwan"
cert.get_subject().L = "Taipei"
cert.get_subject().O = "pysheeet"
cert.get_subject().OU = "cheat sheet"
cert.get_subject().CN = "pythonsheets.com"
cert.set_serial_number(1000)
cert.set_notBefore(now.strftime("%Y%m%d%H%M%SZ").encode())
cert.set_notAfter(expire.strftime("%Y%m%d%H%M%SZ").encode())
cert.set_issuer(cert.get_subject())
cert.set_pubkey(k)
cert.sign(k, 'sha1')
output:
alt_name = [ b"DNS:www.pythonsheeets.com",
b"DNS:doc.pythonsheeets.com" ]
key_usage = [ b"Digital Signature",
b"Non Repudiation",
b"Key Encipherment" ]
# country (countryName, C)
# state or province name (stateOrProvinceName, ST)
# locality (locality, L)
# organization (organizationName, O)
# organizational unit (organizationalUnitName, OU)
# common name (commonName, CN)
req.get_subject().C = "TW"
req.get_subject().ST = "Taiwan"
req.get_subject().L = "Taipei"
req.get_subject().O = "pysheeet"
req.get_subject().OU = "cheat sheet"
req.get_subject().CN = "pythonsheets.com"
req.add_extensions([
crypto.X509Extension( b"basicConstraints",
False,
b"CA:FALSE"),
crypto.X509Extension( b"keyUsage",
False,
b",".join(key_usage)),
crypto.X509Extension( b"subjectAltName",
False,
b",".join(alt_name))
])
req.set_pubkey(key)
req.sign(key, "sha256")
output:
# create a root ca
$ openssl genrsa -out ca-key.pem 2048
Generating RSA private key, 2048 bit long modulus
.....+++
.......................................+++
e is 65537 (0x10001)
(continues on next page)
( )
$ openssl req -x509 -new -nodes -key ca-key.pem \
> -days 10000 -out ca.pem -subj "/CN=root-ca"
# prepare a csr
$ openssl genrsa -out key.pem 2048
Generating RSA private key, 2048 bit long modulus
....+++
......................................+++
e is 65537 (0x10001)
$ python3 x509.py
# prepare openssl.cnf
cat <<EOF > openssl.cnf
> [req]
> req_extensions = v3_req
> distinguished_name = req_distinguished_name
> [req_distinguished_name]
> [ v3_req ]
> basicConstraints = CA:FALSE
> keyUsage = nonRepudiation, digitalSignature, keyEncipherment
> subjectAltName = @alt_names
> [alt_names]
> DNS.1 = www.pythonsheets.com
> DNS.2 = doc.pythonsheets.com
> EOF
# sign a csr
$ openssl x509 -req -in cert.csr -CA ca.pem \
> -CAkey ca-key.pem -CAcreateserial -out cert.pem \
> -days 365 -extensions v3_req -extfile openssl.cnf
Signature ok
subject=/C=TW/ST=Taiwan/L=Taipei/O=pysheeet/OU=cheat sheet/CN=pythonsheets.com
Getting CA Private Key
# check
$ openssl x509 -in cert.pem -text -noout
output:
$ python3 sign.py
$ openssl dgst -sha256 -verify public.key -signature foo.tgz.sha256 foo.tgz
Verified OK
import sys
digest.update(data)
return signer.verify(digest, sig)
( )
with open("foo.tgz", 'rb') as f: data = f.read()
output:
# gernerate public & private key
$ openssl genrsa -out private.key 2048
$ openssl rsa -in private.key -pubout -out public.key
# do verification
$ cat /dev/urandom | head -c 512 | base64 > foo.txt
$ tar -zcf foo.tgz foo.txt
$ openssl dgst -sha256 -sign private.key -out foo.tgz.sha256 foo.tgz
$ python3 verify.py
Verified OK
import base64
import sys
key_text = sys.stdin.read()
# encrypt
cipher_text = cipher.encrypt(b"Hello RSA!")
# do base64 encode
cipher_text = base64.b64encode(cipher_text)
print(cipher_text.decode('utf-8'))
output:
$ openssl genrsa -out private.key 2048
$ openssl rsa -in private.key -pubout -out public.key
$ cat public.key |\
(continues on next page)
( )
> python3 rsa.py |\
> openssl base64 -d -A |\
> openssl rsautl -decrypt -inkey private.key
Hello RSA!
import base64
import sys
# encrypt
cipher_text = cipher.encrypt(b"Hello RSA!")
# do base64 encode
cipher_text = base64.b64encode(cipher_text)
print(cipher_text.decode('utf-8'))
output:
$ openssl genrsa -out private.key 2048
$ openssl rsa -in private.key -pubout -out public.key
$ # check (n, e)
$ openssl rsa -pubin -inform PEM -text -noout < public.key
Public-Key: (2048 bit)
Modulus:
00:93:d5:58:0c:18:cf:91:f0:74:af:1b:40:09:73:
0c:d8:13:23:6c:44:60:0d:83:71:e6:f9:61:85:e5:
b2:d0:8a:73:5c:02:02:51:9a:4f:a7:ab:05:d5:74:
ff:4d:88:3d:e2:91:b8:b0:9f:7e:a9:a3:b2:3c:99:
1c:9a:42:4d:ac:2f:6a:e7:eb:0f:a7:e0:a5:81:e5:
98:49:49:d5:15:3d:53:42:12:08:db:b0:e7:66:2d:
71:5b:ea:55:4e:2d:9b:40:79:f8:7d:6e:5d:f4:a7:
d8:13:cb:13:91:c9:ac:5b:55:62:70:44:25:50:ca:
94:de:78:5d:97:e8:a9:33:66:4f:90:10:00:62:21:
b6:60:52:65:76:bd:a3:3b:cf:2a:db:3f:66:5f:0d:
a3:35:ff:29:34:26:6d:63:a2:a6:77:96:5a:84:c7:
6a:0c:4f:48:52:70:11:8f:85:11:a0:78:f8:60:4b:
5d:d8:4b:b2:64:e5:ec:99:72:c5:a8:1b:ab:5c:09:
e1:80:70:91:06:22:ba:97:33:56:0b:65:d8:f3:35:
66:f8:f9:ea:b9:84:64:8e:3c:14:f7:3d:1f:2c:67:
(continues on next page)
( )
ce:64:cf:f9:c5:16:6b:03:a1:7a:c7:fa:4c:38:56:
ee:e0:4d:5f:ec:46:7e:1f:08:7c:e6:45:a1:fc:17:
1f:91
Exponent: 65537 (0x10001)
$ openssl rsa -pubin -in public.key -modulus -noout |\
> cut -d'=' -f 2 |\
> python3 rsa.py |\
> openssl base64 -d -A |\
> openssl rsautl -decrypt -inkey private.key
Hello RSA!
import base64
import sys
# decode base64
cipher_text = base64.b64decode(sys.stdin.read())
# decrypt
plain_text = cipher.decrypt(cipher_text, None)
print(plain_text.decode('utf-8').strip())
output:
$ openssl genrsa -out private.key 2048
$ openssl rsa -in private.key -pubout -out public.key
$ echo "Hello openssl RSA encrypt" |\
> openssl rsautl -encrypt -pubin -inkey public.key |\
> openssl base64 -e -A |\
> python3 rsa.py
Hello openssl RSA encrypt
( )
import base64
import sys
output:
$ openssl genrsa -out private.key 2048
$ openssl rsa -in private.key -pubout -out public.key
$ cat public.key |\
> python3 rsa.py |\
> openssl base64 -d -A |\
> openssl rsautl -decrypt -oaep -inkey private.key
Hello RSA OAEP!
import base64
import sys
# decode base64
cipher_text = base64.b64decode(sys.stdin.read())
( )
# decrypt
plain_text = cipher.decrypt(cipher_text)
print(plain_text.decode('utf-8').strip())
output:
$ openssl genrsa -out private.key 2048
$ openssl rsa -in private.key -pubout -out public.key
$ echo "Hello RSA encrypt via OAEP" |\
> openssl rsautl -encrypt -pubin -oaep -inkey public.key |\
> openssl base64 -e -A |\
> python3 rsa.py
Hello RSA encrypt via OAEP
import socket
def gen_dsa_key():
private_key = dsa.generate_private_key(
key_size=2048, backend=default_backend())
return private_key, private_key.public_key()
( )
signature = sign_data(alice_msg, alice_private_key)
b = alice.send(signature)
bob_recv_signature = bob.recv(1024)
# attacker modify the msg will make the msg check fail
verify_data(b"I'm attacker!", bob_recv_signature, alice_public_key)
output:
$ python3 test_dsa.py
check msg: b'Hello Bob' success!
recv msg: b"I'm attacker!" not trust!
import struct
import sys
import os
backend = default_backend()
key = os.urandom(32)
iv = os.urandom(16)
def encrypt(ptext):
pad = padding.PKCS7(128).padder()
ptext = pad.update(ptext) + pad.finalize()
alg = algorithms.AES(key)
mode = modes.CBC(iv)
cipher = Cipher(alg, mode, backend=backend)
encryptor = cipher.encryptor()
ctext = encryptor.update(ptext) + encryptor.finalize()
return ctext
print("key: {}".format(key.hex()))
print("iv: {}".format(iv.hex()))
if len(sys.argv) != 3:
raise Exception("usage: cmd [file] [enc file]")
( )
with open(sys.argv[1], 'rb') as f:
plaintext = f.read()
# encrypt file
ciphertext = encrypt(plaintext)
with open(sys.argv[2], 'wb') as f:
f.write(ciphertext)
output:
$ echo "Encrypt file via AES-CBC" > test.txt
$ python3 aes.py test.txt test.enc
key: f239d9609e3f318b7afda7e4bb8db5b8734f504cf67f55e45dfe75f90d24fefc
iv: 8d6383b469f100d25293fb244ccb951e
$ openssl aes-256-cbc -d -in test.enc -out secrets.txt.new \
> -K f239d9609e3f318b7afda7e4bb8db5b8734f504cf67f55e45dfe75f90d24fefc \
> -iv 8d6383b469f100d25293fb244ccb951e
$ cat secrets.txt.new
Encrypt file via AES-CBC
import struct
import sys
import os
backend = default_backend()
return ptext
if len(sys.argv) != 4:
raise Exception("usage: cmd [key] [iv] [file]")
( )
# read cipher text from file
with open(sys.argv[3], 'rb') as f:
ciphertext = f.read()
# decrypt file
key, iv = unhexlify(sys.argv[1]), unhexlify(sys.argv[2])
plaintext = decrypt(key, iv, ciphertext)
print(plaintext)
output:
$ echo "Encrypt file via AES-CBC" > test.txt
$ key=`openssl rand -hex 32`
$ iv=`openssl rand -hex 16`
$ openssl enc -aes-256-cbc -in test.txt -out test.enc -K $key -iv $iv
$ python3 aes.py $key $iv test.enc
import base64
import struct
import sys
import os
backend = default_backend()
# generate salt
salt = os.urandom(8)
7.16. AES CBC mode encrypt via password (using cryptography) 133
python-cheatsheet Documentation, 0.1.0
( )
# pad plaintext
pad = padding.PKCS7(128).padder()
ptext = pad.update(ptext) + pad.finalize()
# create an encryptor
alg = algorithms.AES(key)
mode = modes.CBC(iv)
cipher = Cipher(alg, mode, backend=backend)
encryptor = cipher.encryptor()
# encode base64
ctext = base64.b64encode(ctext)
return ctext
md = globals()[sys.argv[1]]
plaintext = sys.stdin.read().encode('utf-8')
pwd = b"password"
output:
# with md5 digest
$ echo "Encrypt plaintext via AES-CBC from a given password" |\
> python3 aes.py md5 |\
> openssl base64 -d -A |\
> openssl aes-256-cbc -md md5 -d -k password
Encrypt plaintext via AES-CBC from a given password
import base64
import struct
import sys
import os
( )
from hashlib import md5, sha1
backend = default_backend()
# check magic
if ctext[:8] != b'Salted__':
raise Exception("bad magic number")
# get salt
salt = ctext[8:16]
# decrypt
alg = algorithms.AES(key)
mode = modes.CBC(iv)
cipher = Cipher(alg, mode, backend=backend)
decryptor = cipher.decryptor()
ptext = decryptor.update(ctext[16:]) + decryptor.finalize()
# unpad plaintext
unpadder = padding.PKCS7(128).unpadder() # 128 bit
ptext = unpadder.update(ptext) + unpadder.finalize()
return ptext.strip()
md = globals()[sys.argv[1]]
ciphertext = sys.stdin.read().encode('utf-8')
pwd = b"password"
output:
7.17. AES CBC mode decrypt via password (using cryptography) 135
python-cheatsheet Documentation, 0.1.0
import struct
import base64
import sys
# generate salt
salt = struct.pack('=Q', getrandbits(64))
# pad plaintext
plaintext = pad(plaintext)
( )
# ref: openssl/apps/enc.c
ciphertext = b'Salted__' + salt + cipher.encrypt(plaintext)
# encode base64
ciphertext = base64.b64encode(ciphertext)
return ciphertext
md = globals()[sys.argv[1]]
plaintext = sys.stdin.read().encode('utf-8')
pwd = b"password"
output:
# with md5 digest
$ echo "Encrypt plaintext via AES-CBC from a given password" |\
> python3 aes.py md5 |\
> openssl base64 -d -A |\
> openssl aes-256-cbc -md md5 -d -k password
Encrypt plaintext via AES-CBC from a given password
import struct
import base64
import sys
7.19. AES CBC mode decrypt via password (using pycrytpo) 137
python-cheatsheet Documentation, 0.1.0
( )
d = md(d + pwd + salt).digest()
buf += d
return buf[:key_len], buf[key_len:key_len + iv_len]
# check magic
if ciphertext[:8] != b'Salted__':
raise Exception("bad magic number")
# get salt
salt = ciphertext[8:16]
# get key, iv
key, iv = EVP_ByteToKey(pwd, md, salt, 32, 16)
# decrypt
cipher = AES.new(key, AES.MODE_CBC, iv)
return unpad(cipher.decrypt(ciphertext[16:])).strip()
md = globals()[sys.argv[1]]
ciphertext = sys.stdin.read().encode('utf-8')
pwd = b"password"
output:
# with md5 digest
$ echo "Decrypt ciphertext via AES-CBC from a given password" |\
> openssl aes-256-cbc -e -md md5 -salt -A -k password |\
> openssl base64 -e -A |\
> python3 aes.py md5
Decrypt ciphertext via AES-CBC from a given password
( )
>>> b_key = params.generate_private_key() # bob's private key
>>> a_pub_key = a_key.public_key()
>>> b_pub_key = b_key.public_key()
>>> a_shared_key = a_key.exchange(b_pub_key)
>>> b_shared_key = b_key.exchange(a_pub_key)
>>> a_shared_key == b_shared_key
True
backend = default_backend()
p = int("11859949538425015739337467917303613431031019140213666"
"12902540730065402658508634532306628480096346320424639"
"0256567934582260424238844463330887962689642467123")
g = 2
y = int("32155788395534640648739966373159697798396966919821525"
"72238852825117261342483718574508213761865276905503199"
"969908098203345481366464874759377454476688391248")
x = int("409364065449673443397833358558926598469347813468816037"
"268451847116982490733450463194921405069999008617231539"
"7147035896687401350877308899732826446337707128")
params = dh.DHParameterNumbers(p, g)
public = dh.DHPublicNumbers(y, params)
private = dh.DHPrivateNumbers(x, public)
key = private.private_key(backend)
(continues on next page)
( )
shared_key = key.exchange(public.public_key(backend))
Table of Contents
141
python-cheatsheet Documentation, 0.1.0
( )
... task,arg = q.get()
... print task(arg)
... q.task_done()
...
>>> t1 = Thread(target=producer)
>>> t2 = Thread(target=consumer)
>>> t1.start();t2.start()
class Worker(Thread):
def __init__(self,queue):
super(Worker, self).__init__()
self._q = queue
self.daemon = True
self.start()
def run(self):
while True:
f,args,kwargs = self._q.get()
try:
print f(*args, **kwargs)
except Exception as e:
print e
self._q.task_done()
class ThreadPool(object):
def __init__(self, num_t=5):
self._q = Queue(num_t)
# Create Worker Thread
for _ in range(num_t):
Worker(self._q)
def add_task(self,f,*args,**kwargs):
self._q.put((f, args, kwargs))
def wait_complete(self):
self._q.join()
def fib(n):
if n <= 2:
return 1
return fib(n-1)+fib(n-2)
if __name__ == '__main__':
pool = ThreadPool()
for _ in range(3):
pool.add_task(fib,35)
pool.wait_complete()
pool = ThreadPool(10)
def profile(func):
def wrapper(*args, **kwargs):
print func.__name__
s = time.time()
func(*args, **kwargs)
e = time.time()
print "cost: {0}".format(e-s)
return wrapper
@profile
def pool_map():
res = pool.map(lambda x:x**2,
range(999999))
@profile
def ordinary_map():
res = map(lambda x:x**2,
range(999999))
pool_map()
ordinary_map()
output:
$ python test_threadpool.py
pool_map
cost: 0.562669038773
ordinary_map
cost: 0.38525390625
( )
... lock.acquire()
... print "task{0} get".format(id)
... lock.release()
...
>>> t1=Thread(target=getlock,args=(1,))
>>> t2=Thread(target=getlock,args=(2,))
>>> t1.start();t2.start()
task1 get
task2 get
8.8 Deadlock
>>> t1.isAlive()
True
>>> t2.isAlive()
True
Using RLock
# ref: An introduction to Python Concurrency - David Beazley
from threading import Thread
from threading import RLock
import time
class monitor(object):
lock = RLock()
def foo(self,tid):
with monitor.lock:
print "%d in foo" % tid
time.sleep(5)
self.ker(tid)
def ker(self,tid):
with monitor.lock:
print "%d in ker" % tid
m = monitor()
def task1(id):
m.foo(id)
def task2(id):
m.ker(id)
t1 = Thread(target=task1,args=(1,))
t2 = Thread(target=task2,args=(2,))
t1.start()
t2.start()
t1.join()
t2.join()
output:
$ python monitor.py
1 in foo
1 in ker
2 in ker
Using Semaphore
from threading import Thread
from threading import Semaphore
from random import random
import time
# limit resource to 3
sema = Semaphore(3)
def foo(tid):
with sema:
print "%d acquire sema" % tid
(continues on next page)
( )
wt = random()*5
time.sleep(wt)
print "%d release sema" % tid
threads = []
for _t in range(5):
t = Thread(target=foo,args=(_t,))
threads.append(t)
t.start()
for _t in threads:
_t.join()
output:
python semaphore.py
0 acquire sema
1 acquire sema
2 acquire sema
0 release sema
3 acquire sema
2 release sema
4 acquire sema
1 release sema
4 release sema
3 release sema
Using ’event’
e = Event()
def worker(id):
print "%d wait event" % id
e.wait()
print "%d get event set" % id
t1=Thread(target=worker,args=(1,))
t2=Thread(target=worker,args=(2,))
t3=Thread(target=worker,args=(3,))
t1.start()
t2.start()
t3.start()
output:
python event.py
1 wait event
2 wait event
3 wait event
2 get event set
3 get event set
1 get event set
Using ’condition’
import threading
import heapq
import time
import random
class PriorityQueue(object):
def __init__(self):
self._q = []
self._count = 0
self._cv = threading.Condition()
def __str__(self):
return str(self._q)
def __repr__(self):
return self._q
def pop(self):
with self._cv:
while len(self._q) == 0:
print("wait...")
self._cv.wait()
ret = heapq.heappop(self._q)[-1]
return ret
priq = PriorityQueue()
def producer():
while True:
print(priq.pop())
def consumer():
while True:
time.sleep(3)
print("consumer put value")
priority = random.random()
priq.put(priority,priority*10)
( )
for _ in range(3):
priority = random.random()
priq.put(priority,priority*10)
t1=threading.Thread(target=producer)
t2=threading.Thread(target=consumer)
t1.start();t2.start()
t1.join();t2.join()
output:
python3 thread_safe.py
0.6657491871045683
0.5278797439991247
0.20990624606296315
wait...
consumer put value
0.09123101305407577
wait...
8.13 Multiprocessing
def spawn(f):
def fun(pipe,x):
pipe.send(f(x))
pipe.close()
return fun
def parmap(f,X):
pipe=[Pipe() for x in X]
proc=[Process(target=spawn(f),
args=(c,x))
for x,(p,c) in izip(X,pipe)]
[p.start() for p in proc]
[p.join() for p in proc]
return [p.recv() for (p,c) in pipe]
import signal
import os
import time
NUM_PROCESS = 10
def aurora(n):
while True:
time.sleep(n)
if __name__ == "__main__":
procs = [Process(target=aurora, args=(x,))
for x in range(NUM_PROCESS)]
try:
for p in procs:
p.daemon = True
p.start()
[p.join() for p in procs]
finally:
for p in procs:
if not p.is_alive(): continue
os.kill(p.pid, signal.SIGKILL)
tasks = deque()
r_wait = {}
s_wait = {}
def fib(n):
if n <= 2:
return 1
return fib(n-1)+fib(n-2)
def run():
while any([tasks,r_wait,s_wait]):
(continues on next page)
( )
while not tasks:
# polling
rr, sr, _ = select(r_wait, s_wait, {})
for _ in rr:
tasks.append(r_wait.pop(_))
for _ in sr:
tasks.append(s_wait.pop(_))
try:
task = tasks.popleft()
why,what = task.next()
if why == 'recv':
r_wait[what] = task
elif why == 'send':
s_wait[what] = task
else:
raise RuntimeError
except StopIteration:
pass
def fib_server():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)
sock.bind(('localhost',5566))
sock.listen(5)
while True:
yield 'recv', sock
c, a = sock.accept()
tasks.append(fib_handler(c))
def fib_handler(client):
while True:
yield 'recv', client
req = client.recv(1024)
if not req:
break
resp = fib(int(req))
yield 'send', client
client.send(str(resp)+'\n')
client.close()
tasks.append(fib_server())
run()
output: (bash 1)
$ nc loalhost 5566
20
6765
output: (bash 2)
$ nc localhost 5566
10
55
8.18 PoolExecutor
# demo GIL
from concurrent import futures
import time
def fib(n):
if n <= 2:
return 1
return fib(n-1) + fib(n-2)
def thread():
s = time.time()
with futures.ThreadPoolExecutor(2) as e:
res = e.map(fib, [35]*2)
for _ in res:
print(_)
e = time.time()
print("thread cost: {}".format(e-s))
def process():
s = time.time()
with futures.ProcessPoolExecutor(2) as e:
res = e.map(fib, [35]*2)
for _ in res:
print(_)
e = time.time()
print("pocess cost: {}".format(e-s))
( )
>>> process()
9227465
9227465
pocess cost: 5.538189888000488
def fib(n):
if n <= 2:
return 1
return fib(n-1) + fib(n-2)
with futures.ThreadPoolExecutor(3) as e:
fut = e.submit(fib, 30)
res = fut.result()
print(res)
# equal to
e = futures.ThreadPoolExecutor(3)
fut = e.submit(fib, 30)
fut.result()
e.shutdown(wait=True)
print(res)
output:
$ python3 thread_pool_exec.py
832040
832040
def fib(n):
if n <= 2:
return 1
return fib(n-1) + fib(n-2)
def handler(future):
res = future.result()
print("res: {}".format(res))
def thread_v1():
with futures.ThreadPoolExecutor(3) as e:
for _ in range(3):
f = e.submit(fib, 30+_)
(continues on next page)
( )
f.add_done_callback(handler)
print("end")
def thread_v2():
to_do = []
with futures.ThreadPoolExecutor(3) as e:
for _ in range(3):
fut = e.submit(fib, 30+_)
to_do.append(fut)
for _f in futures.as_completed(to_do):
res = _f.result()
print("res: {}".format(res))
print("end")
output:
$ python3 -i fut.py
>>> thread_v1()
res: 832040
res: 1346269
res: 2178309
end
>>> thread_v2()
res: 832040
res: 1346269
res: 2178309
end
def spam():
raise RuntimeError
def handler(future):
print("callback handler")
try:
res = future.result()
except RuntimeError:
print("get RuntimeError")
def thread_spam():
with futures.ThreadPoolExecutor(2) as e:
f = e.submit(spam)
f.add_done_callback(handler)
output:
$ python -i fut_err.py
>>> thread_spam()
callback handler
get RuntimeError
Table of Contents
157
python-cheatsheet Documentation, 0.1.0
output:
$ python sqlalchemy_url.py
postgres://postgres:[email protected]:5432
sqlite:///db.sqlite
db_uri = "sqlite:///db.sqlite"
engine = create_engine(db_uri)
( )
# DBAPI - PEP249
# create table
engine.execute('CREATE TABLE "EX1" ('
'id INTEGER NOT NULL,'
'name VARCHAR, '
'PRIMARY KEY (id));')
# insert a raw
engine.execute('INSERT INTO "EX1" '
'(id, name) '
'VALUES (1,"raw1")')
# select *
result = engine.execute('SELECT * FROM '
'"EX1"')
for _r in result:
print _r
# delete *
engine.execute('DELETE from "EX1" where id=1;')
result = engine.execute('SELECT * FROM "EX1"')
print result.fetchall()
db_uri = 'sqlite:///db.sqlite'
engine = create_engine(db_uri)
# Create connection
conn = engine.connect()
# Begin transaction
trans = conn.begin()
conn.execute('INSERT INTO "EX1" (name) '
'VALUES ("Hello")')
trans.commit()
# Close connection
conn.close()
db_uri = 'sqlite:///db.sqlite'
engine = create_engine(db_uri)
( )
metadata = MetaData(engine)
# Declare a table
table = Table('Example',metadata,
Column('id',Integer, primary_key=True),
Column('name',String))
# Create all tables
metadata.create_all()
for _t in metadata.tables:
print "Table: ", _t
db_uri = 'sqlite:///db.sqlite'
engine = create_engine(db_uri)
inspector = inspect(engine)
db_uri = 'sqlite:///db.sqlite'
engine = create_engine(db_uri)
( )
db_uri = 'sqlite:///db.sqlite'
engine = create_engine(db_uri)
# Get Table
ex_table = metadata.tables['Example']
print ex_table
db_uri = 'sqlite:///db.sqlite'
engine = create_engine(db_uri)
meta = MetaData(engine)
t2 = Table('EX2', meta,
Column('id',Integer, primary_key=True),
Column('val',Integer))
# Create all tables in meta
meta.create_all()
db_uri = 'sqlite:///db.sqlite'
engine = create_engine(db_uri)
meta = MetaData(engine)
t1 = Table('Table_1', meta,
Column('id', Integer, primary_key=True),
Column('name',String))
t2 = Table('Table_2', meta,
(continues on next page)
( )
Column('id', Integer, primary_key=True),
Column('val',Integer))
t1.create()
db_url = "sqlite://"
engine = create_engine(db_url)
Base = declarative_base()
class TemplateTable(object):
id = Column(Integer, primary_key=True)
name = Column(String)
age = Column(Integer)
Base.metadata.create_all(bind=engine)
( )
engine = create_engine(URL(**db_url))
m = MetaData()
table = Table('Test', m,
Column('id', Integer, primary_key=True),
Column('key', String, nullable=True),
Column('val', String))
table.create(engine)
inspector = inspect(engine)
print 'Test' in inspector.get_table_names()
table.drop(engine)
inspector = inspect(engine)
print 'Test' in inspector.get_table_names()
output:
$ python sqlalchemy_drop.py
$ True
$ False
meta = MetaData()
t = Table('ex_table', meta,
Column('id', Integer, primary_key=True),
Column('key', String),
Column('val', Integer))
# Get Table Name
print t.name
# Get Columns
print t.columns.keys()
# Get Column
c = t.c.key
print c.name
# Or
c = t.columns.key
print c.name
meta = MetaData()
table = Table('example', meta,
Column('id', Integer, primary_key=True),
Column('l_name', String),
Column('f_name', String))
# sql expression binary object
print repr(table.c.l_name == 'ed')
# exhbit sql expression
print str(table.c.l_name == 'ed')
# comparison operator
print repr(table.c.id > 3)
# or expression
print (table.c.id > 5) | (table.c.id < 2)
# Equal to
print or_(table.c.id > 5, table.c.id < 2)
# + means "addition"
print (table.c.id + 5)
# or means "string concatenation"
print (table.c.l_name + "some name")
# in expression
print (table.c.l_name.in_(['a','b']))
db_uri = 'sqlite:///db.sqlite'
engine = create_engine(db_uri)
(continues on next page)
( )
# create table
meta = MetaData(engine)
table = Table('user', meta,
Column('id', Integer, primary_key=True),
Column('l_name', String),
Column('f_name', String))
meta.create_all()
db_uri = 'sqlite:///db.sqlite'
engine = create_engine(db_uri)
conn = engine.connect()
meta = MetaData(engine,reflect=True)
table = meta.tables['user']
# or equal to
select_st = table.select().where(
table.c.l_name == 'Hello')
res = conn.execute(select_st)
for _row in res: print _row
( )
res = conn.execute(select_st)
for _row in res: print _row
db_uri = 'sqlite:///db.sqlite'
engine = create_engine(db_uri)
# insert
conn = engine.connect()
conn.execute(email_t.insert(),[
{'email':'ker@test','name':'Hi'},
{'email':'yo@test','name':'Hello'}])
# join statement
join_obj = user_t.join(email_t,
email_t.c.name == user_t.c.l_name)
# using select_from
sel_st = select(
[user_t.c.l_name, email_t.c.email]).select_from(join_obj)
res = conn.execute(sel_st)
for _row in res: print _row
( )
db_uri = 'sqlite:///db.sqlite'
engine = create_engine(db_uri)
conn = engine.connect()
Modal = declarative_base()
class Example(Modal):
__tablename__ = "ex_t"
id = Column(Integer, primary_key=True)
name = Column(String(20))
db_uri = 'sqlite:///db.sqlite'
engine = create_engine(db_uri)
Modal.metadata.create_all(engine)
db = {'drivername': 'postgres',
'username': 'postgres',
'password': 'postgres',
'host': '192.168.99.100',
'port': 5432}
url = URL(**db)
engine = create_engine(url)
metadata = MetaData()
metadata.reflect(bind=engine)
inspector = inspect(engine)
print inspector.get_table_names()
output:
$ python sqlalchemy_create.py
[u'table1', u'table2', u'table3']
( )
'port': 5432}
engine = create_engine(URL(**db_url))
create_table('Table1',
Column('id', Integer, primary_key=True),
Column('name', String))
create_table('Table2',
Column('id', Integer, primary_key=True),
Column('key', String),
Column('val', String))
inspector = inspect(engine)
for _t in inspector.get_table_names(): print _t
output:
$ python sqlalchemy_dynamic.py
Table1
Table2
Base = declarative_base()
class TestTable(Base):
__tablename__ = 'Test Table'
id = Column(Integer, primary_key=True)
key = Column(String, nullable=False)
val = Column(String)
(continues on next page)
( )
date = Column(DateTime, default=datetime.utcnow)
# create tables
Base.metadata.create_all(bind=engine)
# create session
Session = sessionmaker()
Session.configure(bind=engine)
session = Session()
class TestTable(Base):
__tablename__ = 'Test Table'
id = Column(Integer, primary_key=True)
key = Column(String, nullable=False)
val = Column(String)
date = Column(DateTime, default=datetime.utcnow)
# create tables
Base.metadata.create_all(bind=engine)
# create session
Session = sessionmaker()
Session.configure(bind=engine)
session = Session()
(continues on next page)
( )
try:
# add row to database
row = TestTable(key="hello", val="world")
session.add(row)
session.commit()
output:
$ python sqlalchemy_update.py
original: hello world
update: Hello World
class TestTable(Base):
__tablename__ = 'Test Table'
id = Column(Integer, primary_key=True)
key = Column(String, nullable=False)
(continues on next page)
( )
val = Column(String)
date = Column(DateTime, default=datetime.utcnow)
# create tables
Base.metadata.create_all(bind=engine)
# create session
Session = sessionmaker()
Session.configure(bind=engine)
session = Session()
output:
$ python sqlalchemy_delete.py
<__main__.TestTable object at 0x104eb8f50>
[]
Base = declarative_base()
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String)
addresses = relationship("Address", backref="user")
class Address(Base):
__tablename__ = 'address'
id = Column(Integer, primary_key=True)
email = Column(String)
user_id = Column(Integer, ForeignKey('user.id'))
u1 = User()
a1 = Address()
print u1.addresses
print a1.user
u1.addresses.append(a1)
(continues on next page)
( )
print u1.addresses
print a1.user
output:
$ python sqlalchemy_relationship.py
[]
None
[<__main__.Address object at 0x10c4edb50>]
<__main__.User object at 0x10c4ed810>
import json
base = declarative_base()
class Node(base):
__tablename__ = 'node'
id = Column(Integer, primary_key=True)
label = Column(String)
friends = relationship('Node',
secondary=association,
primaryjoin=id==association.c.left,
secondaryjoin=id==association.c.right,
backref='left')
def to_json(self):
return dict(id=self.id,
friends=[_.label for _ in self.friends])
print('----> right')
print(json.dumps([_.to_json() for _ in nodes], indent=2))
( )
print('----> left')
print(json.dumps([_n.to_json() for _n in nodes[1].left], indent=2))
output:
----> right
[
{
"friends": [
"node_1",
"node_2"
],
"id": null
},
{
"friends": [
"node_2"
],
"id": null
},
{
"friends": [],
"id": null
}
]
----> left
[
{
"friends": [
"node_1",
"node_2"
],
"id": null
}
]
( )
Base = declarative_base()
class User(Base):
__tablename__ = 'User'
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
fullname = Column(String, nullable=False)
birth = Column(DateTime)
# create tables
engine = create_engine(URL(**db_url))
Base.metadata.create_all(bind=engine)
users = [
User(name='ed',
fullname='Ed Jones',
birth=datetime(1989,7,1)),
User(name='wendy',
fullname='Wendy Williams',
birth=datetime(1983,4,1)),
User(name='mary',
fullname='Mary Contrary',
birth=datetime(1990,1,30)),
User(name='fred',
fullname='Fred Flinstone',
birth=datetime(1977,3,12)),
User(name='justin',
fullname="Justin Bieber")]
# create session
Session = sessionmaker()
Session.configure(bind=engine)
session = Session()
# add_all
session.add_all(users)
session.commit()
( )
print _row.name, _row.fullname, _row.birth
output:
----> order_by(id):
ed Ed Jones 1989-07-01 00:00:00
wendy Wendy Williams 1983-04-01 00:00:00
mary Mary Contrary 1990-01-30 00:00:00
fred Fred Flinstone 1977-03-12 00:00:00
justin Justin Bieber None
----> order_by(desc(id)):
justin Justin Bieber None
fred Fred Flinstone 1977-03-12 00:00:00
mary Mary Contrary 1990-01-30 00:00:00
(continues on next page)
( )
wendy Wendy Williams 1983-04-01 00:00:00
ed Ed Jones 1989-07-01 00:00:00
----> order_by(date):
fred Fred Flinstone 1977-03-12 00:00:00
wendy Wendy Williams 1983-04-01 00:00:00
ed Ed Jones 1989-07-01 00:00:00
mary Mary Contrary 1990-01-30 00:00:00
justin Justin Bieber None
----> EQUAL:
wendy Wendy Williams 1983-04-01 00:00:00
----> IN:
ed Ed Jones 1989-07-01 00:00:00
wendy Wendy Williams 1983-04-01 00:00:00
----> AND:
ed Ed Jones 1989-07-01 00:00:00
----> OR:
ed Ed Jones 1989-07-01 00:00:00
wendy Wendy Williams 1983-04-01 00:00:00
----> NULL:
justin Justin Bieber
----> LIKE
ed Ed Jones
fred Fred Flinstone
( )
Column,
Integer,
String,
ForeignKey)
meta = MetaData(bind=engine)
class Address(object):
def __init__(self, email):
self.email = email
# create table
meta.create_all()
# create session
Session = sessionmaker()
Session.configure(bind=engine)
session = Session()
( )
# query result
u = session.query(User).filter(User.name == 'Hello').first()
print u.name, u.fullname, u.password
finally:
session.close()
output:
$ python map_table_class.py
Hello HelloWorld ker
db_url = "sqlite://"
engine = create_engine(db_url)
metadata = MetaData(engine)
class TableTemp(object):
def __init__(self, name):
self.name = name
def get_table(name):
if name in metadata.tables:
table = metadata.tables[name]
else:
table = Table(name, metadata,
Column('id', Integer, primary_key=True),
Column('name', String))
table.create(engine)
( )
Session = scoped_session(sessionmaker(bind=engine))
try:
Session.add(t(name='foo'))
Session.add(t(name='bar'))
for _ in Session.query(t).all(): print _.name
except Exception as e:
Session.rollback()
finally:
Session.close()
output:
$ python get_table.py
foo
bar
Base = declarative_base()
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String)
addresses = relationship("Address", backref="user")
class Address(Base):
__tablename__ = 'address'
id = Column(Integer, primary_key=True)
email = Column(String)
user_id = Column(Integer, ForeignKey('user.id'))
# create engine
engine = create_engine(URL(**db_url))
# create tables
Base.metadata.create_all(bind=engine)
# create session
Session = sessionmaker()
(continues on next page)
( )
Session.configure(bind=engine)
session = Session()
user = User(name='user1')
mail1 = Address(email='[email protected]')
mail2 = Address(email='[email protected]')
user.addresses.extend([mail1, mail2])
session.add(user)
session.add_all([mail1, mail2])
session.commit()
output:
$ python sqlalchemy_join.py
user1 [email protected]
user1 [email protected]
db_url = 'sqlite://'
engine = create_engine(db_url)
Base = declarative_base()
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
name = Column(String)
children = relationship('Child', back_populates='parent')
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
name = Column(String)
parent_id = Column(Integer, ForeignKey('parent.id'))
(continues on next page)
( )
parent = relationship('Parent', back_populates='children')
Base.metadata.create_all(bind=engine)
Session = scoped_session(sessionmaker(bind=engine))
p1 = Parent(name="Alice")
p2 = Parent(name="Bob")
c1 = Child(name="foo")
c2 = Child(name="bar")
c3 = Child(name="ker")
c4 = Child(name="cat")
try:
Session.add(p1)
Session.add(p2)
Session.commit()
# print result
for _p, _c in q.all():
print 'parent: {}, num_child: {}'.format(_p.name, _c)
finally:
Session.remove()
output:
$ python join_group_by.py
parent: Alice, num_child: 3
parent: Bob, num_child: 1
engine = create_engine(URL(**db_url))
Base = declarative_base()
(continues on next page)
( )
create_table('Table1', {
'__tablename__': 'Table1',
'id': Column(Integer, primary_key=True),
'name': Column(String)})
create_table('Table2', {
'__tablename__': 'Table2',
'id': Column(Integer, primary_key=True),
'key': Column(String),
'val': Column(String)})
inspector = inspect(engine)
for _t in inspector.get_table_names(): print _t
output:
$ python sqlalchemy_dynamic_orm.py
Table1
Table2
engine = create_engine('sqlite://')
base = declarative_base()
@event.listens_for(engine, 'engine_disposed')
def receive_engine_disposed(engine):
print("engine dispose")
class Table(base):
__tablename__ = 'example table'
id = Column(Integer, primary_key=True)
base.metadata.create_all(bind=engine)
session = sessionmaker(bind=engine)()
try:
(continues on next page)
( )
try:
row = Table()
session.add(row)
except Exception as e:
session.rollback()
raise
finally:
session.close()
finally:
engine.dispose()
output:
$ python db_dispose.py
engine dispose
: Be careful. Close session does not mean close database connection. SQLAlchemy session generally represents
the transactions, not connections.
url = 'sqlite://'
engine = create_engine(url)
base = declarative_base()
class Table(base):
__tablename__ = 'table'
id = Column(Integer, primary_key=True)
key = Column(String)
val = Column(String)
base.metadata.create_all(bind=engine)
session = sessionmaker(bind=engine)()
try:
t = Table(key="key", val="val")
try:
print(t.key, t.val)
session.add(t)
session.commit()
(continues on next page)
( )
except Exception as e:
print(e)
session.rollback()
finally:
session.close()
output:
$ python sql.py
key val
Cannot use the object after close the session
9.33. Cannot use the object after close the session 185
python-cheatsheet Documentation, 0.1.0
Table of Contents
187
python-cheatsheet Documentation, 0.1.0
– decorator @asynccontextmanager
– What loop.sock_* do?
– Simple asyncio connection pool
– Simple asyncio UDP echo server
– Simple asyncio web server
– Simple HTTPS asyncio web server
– Simple asyncio WSGI web server
import asyncio
import inspect
from functools import wraps
Future = asyncio.futures.Future
def coroutine(func):
"""Simple prototype of coroutine"""
@wraps(func)
def coro(*a, **k):
res = func(*a, **k)
if isinstance(res, Future) or inspect.isgenerator(res):
res = yield from res
return res
return coro
@coroutine
def foo():
yield from asyncio.sleep(1)
print("Hello Foo")
@asyncio.coroutine
def bar():
print("Hello Bar")
loop = asyncio.get_event_loop()
tasks = [loop.create_task(foo()),
loop.create_task(bar())]
loop.run_until_complete(
asyncio.wait(tasks))
loop.close()
output:
$ python test.py
Hello Bar
Hello Foo
import asyncio
Future = asyncio.futures.Future
class Task(Future):
"""Simple prototype of Task"""
@asyncio.coroutine
def foo():
yield from asyncio.sleep(3)
print("Hello Foo")
@asyncio.coroutine
def bar():
yield from asyncio.sleep(1)
print("Hello Bar")
loop = asyncio.get_event_loop()
tasks = [Task(foo(), loop=loop),
loop.create_task(bar())]
loop.run_until_complete(
asyncio.wait(tasks))
loop.close()
output:
$ python test.py
Hello Bar
hello Foo
import asyncio
from collections import deque
def done_callback(fut):
fut._loop.stop()
class Loop:
"""Simple event loop prototype"""
def __init__(self):
self._ready = deque()
self._stopping = False
def run_forever(self):
"""Run tasks until stop"""
try:
while True:
self._run_once()
if self._stopping:
break
finally:
self._stopping = False
def _run_once(self):
"""Run task at once"""
ntodo = len(self._ready)
(continues on next page)
( )
for i in range(ntodo):
t, a = self._ready.popleft()
t(*a)
def stop(self):
self._stopping = True
def close(self):
self._ready.clear()
def get_debug(self):
return False
@asyncio.coroutine
def foo():
print("Foo")
@asyncio.coroutine
def bar():
print("Bar")
loop = Loop()
tasks = [loop.create_task(foo()),
loop.create_task(bar())]
loop.run_until_complete(
asyncio.wait(tasks))
loop.close()
output:
$ python test.py
Foo
Bar
import asyncio
waiter = loop.create_future()
counter = len(fs)
def _on_complete(f):
nonlocal counter
counter -= 1
if counter <= 0 and not waiter.done():
waiter.set_result(None)
for f in fs:
f.add_done_callback(_on_complete)
(continues on next page)
( )
loop = asyncio.get_event_loop()
try:
print("---> wait")
loop.run_until_complete(
wait([slow_task(_) for _ in range(1,3)]))
print("---> asyncio.wait")
loop.run_until_complete(
asyncio.wait([slow_task(_) for _ in range(1,3)]))
finally:
loop.close()
output:
---> wait
sleep "1" sec
sleep "2" sec
---> asyncio.wait
sleep "1" sec
sleep "2" sec
( )
...
>>> async def main():
... obj = await SlowObj(3)
...
>>> loop.run_until_complete(main())
__init__
__await__ sleep(3)
ok
( )
... await asyncio.sleep(n)
... print("sleep: {} sec".format(n))
...
>>> coro = loop.create_task(task(3))
>>> loop.run_until_complete(coro)
num tasks in queue: 0
num tasks in queue: 1
num tasks in queue: 0
sleep: 3 sec
num tasks in queue: 0
>>> loop.close()
import asyncio
import socket
host = 'localhost'
port = 9527
loop = asyncio.get_event_loop()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.setblocking(False)
s.bind((host, port))
s.listen(10)
( )
loop.create_task(handler(conn))
loop.create_task(server())
loop.run_forever()
loop.close()
output: (bash 1)
$ nc localhost 9527
Hello
Hello
output: (bash 2)
$ nc localhost 9527
World
World
# using selectors
# ref: PyCon 2015 - David Beazley
import asyncio
import socket
import selectors
from collections import deque
@asyncio.coroutine
def read_wait(s):
yield 'read_wait', s
@asyncio.coroutine
def write_wait(s):
yield 'write_wait', s
class Loop:
"""Simple loop prototype"""
def __init__(self):
self.ready = deque()
self.selector = selectors.DefaultSelector()
@asyncio.coroutine
def sock_accept(self, s):
yield from read_wait(s)
return s.accept()
@asyncio.coroutine
def sock_recv(self, c, mb):
yield from read_wait(c)
return c.recv(mb)
@asyncio.coroutine
(continues on next page)
( )
def sock_sendall(self, c, m):
while m:
yield from write_wait(c)
nsent = c.send(m)
m = m[nsent:]
def run_forever(self):
while True:
self._run_once()
def _run_once(self):
while not self.ready:
events = self.selector.select()
for k, _ in events:
self.ready.append(k.data)
self.selector.unregister(k.fileobj)
while self.ready:
self.cur_t = ready.popleft()
try:
op, *a = self.cur_t.send(None)
getattr(self, op)(*a)
except StopIteration:
pass
loop = Loop()
host = 'localhost'
port = 9527
s = socket.socket(
socket.AF_INET,
socket.SOCK_STREAM, 0)
s.setsockopt(
socket.SOL_SOCKET,
socket.SO_REUSEADDR, 1)
s.setblocking(False)
s.bind((host, port))
s.listen(10)
@asyncio.coroutine
def handler(c):
while True:
msg = yield from loop.sock_recv(c, 1024)
if not msg:
break
yield from loop.sock_sendall(c, msg)
c.close()
( )
@asyncio.coroutine
def server():
while True:
c, addr = yield from loop.sock_accept(s)
loop.create_task(handler(c))
loop.create_task(server())
loop.run_forever()
import asyncio
class EchoProtocol(asyncio.Protocol):
loop = asyncio.get_event_loop()
coro = loop.create_server(EchoProtocol, 'localhost', 5566)
server = loop.run_until_complete(coro)
try:
loop.run_forever()
except:
loop.run_until_complete(server.wait_closed())
finally:
loop.close()
output:
# console 1
$ nc localhost 5566
Hello
Hello
# console 2
$ nc localhost 5566
World
World
import asyncio
import ssl
(continues on next page)
( )
def make_header():
head = b'HTTP/1.1 200 OK\r\n'
head += b'Content-Type: text/html\r\n'
head += b'\r\n'
return head
def make_body():
resp = b"<html>"
resp += b"<h1>Hello SSL</h1>"
resp += b"</html>"
return resp
sslctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
sslctx.load_cert_chain(certfile='./root-ca.crt',
keyfile='./root-ca.key')
class Service(asyncio.Protocol):
try:
loop = asyncio.get_event_loop()
loop.run_until_complete(start())
finally:
loop.close()
output:
import asyncio
import socket
loop = asyncio.get_event_loop()
return server
class EchoProtocol(asyncio.Protocol):
def connection_made(self, transport):
peername = transport.get_extra_info('peername')
print('Connection from {}'.format(peername))
self.transport = transport
try:
loop.run_forever()
finally:
server.close()
loop.run_until_complete(server.wait_closed())
loop.close()
output:
# console1
$ nc localhost 5566
Hello
Hello
# console2
$ nc localhost 5566
asyncio
asyncio
# ref: PEP-0492
# need Python >= 3.5
( )
1
2
3
# ref: PEP-0492
# need Python >= 3.5
( )
>>> async def hello():
... async with AsyncCtxMgr() as m:
... print("hello block")
...
>>> async def world():
... print("world block")
...
>>> t = loop.create_task(world())
>>> loop.run_until_complete(hello())
world block
__anter__
hello block
__aexit__
( )
...
>>> async def main():
... async with coro("Hello") as m:
... await asyncio.sleep(1)
... print(m)
...
>>> loop = asyncio.get_event_loop()
>>> loop.run_until_complete(main())
Hello
done
import asyncio
import socket
( )
self.remove_writer(fd)
try:
n = sock.send(data)
except (BlockingIOError, InterruptedError):
n = 0
except Exception as e:
fut.set_exception(e)
return
if n == len(data):
fut.set_result(None)
else:
if n:
data = data[n:]
self.add_writer(fd, sock, data, fut, True)
return fut
while True:
conn, addr = await loop.sock_accept(sock)
loop.create_task(handler(loop, conn))
EventLoop = asyncio.SelectorEventLoop
EventLoop.sock_accept = sock_accept
EventLoop.sock_recv = sock_recv
EventLoop.sock_sendall = sock_sendall
loop = EventLoop()
try:
loop.run_until_complete(server(loop))
except KeyboardInterrupt:
pass
finally:
loop.close()
output:
# console 1
$ python3 async_sock.py &
$ nc localhost 9527
Hello
Hello
# console 2
$ nc localhost 9527
(continues on next page)
( )
asyncio
asyncio
import asyncio
import socket
import uuid
class Transport:
self._loop = loop
self._host = host
self._port = port
self._sock = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
self._sock.setblocking(False)
self._uuid = uuid.uuid1()
def close(self):
if self._sock: self._sock.close()
@property
def alive(self):
ret = True if self._sock else False
return ret
@property
def uuid(self):
return self._uuid
class ConnectionPool:
( )
self._loop = loop
def __await__(self):
for _c in self._conns:
yield from _c.connect().__await__()
return self
for _c in self._conns:
if _c.alive and not _c.used:
_c.used = True
fut.set_result(_c)
break
else:
loop.call_soon(self.getconn, fut)
return fut
def close(self):
for _c in self._conns:
_c.close()
# generate messages
msgs = ['coro_{}'.format(_).encode('utf-8') for _ in range(5)]
# create tasks
fs = [loop.create_task(handler(pool, _m)) for _m in msgs]
( )
# wait all tasks done
done, pending = await asyncio.wait(fs)
for _ in done: print(_.result())
finally:
pool.close()
loop = asyncio.get_event_loop()
host = '127.0.0.1'
port = 9527
try:
loop.run_until_complete(main(loop, host, port))
except KeyboardInterrupt:
pass
finally:
loop.close()
output:
$ ncat -l 9527 --keep-open --exec "/bin/cat" &
$ python3 conn_pool.py
echo: b'coro_1'
echo: b'coro_0'
echo: b'coro_2'
echo: b'coro_3'
echo: b'coro_4'
import asyncio
import socket
loop = asyncio.get_event_loop()
host = 'localhost'
port = 3553
sock.bind((host, port))
try:
data, addr = sock.recvfrom(n_bytes)
except (BlockingIOError, InterruptedError):
(continues on next page)
( )
loop.add_reader(fd, recvfrom, loop, sock, n_bytes, fut, True)
else:
fut.set_result((data, addr))
return fut
try:
n = sock.sendto(data, addr)
except (BlockingIOError, InterruptedError):
loop.add_writer(fd, sendto, loop, sock, data, addr, fut, True)
else:
fut.set_result(n)
return fut
try:
loop.run_until_complete(udp_server(loop, sock))
finally:
loop.close()
output:
$ python3 udp_server.py
$ nc -u localhost 3553
Hello UDP
Hello UDP
import asyncio
import socket
host = 'localhost'
port = 9527
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.setblocking(False)
s.bind((host, port))
s.listen(10)
loop = asyncio.get_event_loop()
( )
def make_header():
header = b"HTTP/1.1 200 OK\r\n"
header += b"Content-Type: text/html\r\n"
header += b"\r\n"
return header
def make_body():
resp = b'<html>'
resp += b'<body><h3>Hello World</h3></body>'
resp += b'</html>'
return resp
try:
loop.run_until_complete(server(s, loop))
except KeyboardInterrupt:
pass
finally:
loop.close()
s.close()
# Then open browser with url: localhost:9527
import asyncio
import socket
import ssl
def make_header():
head = b'HTTP/1.1 200 OK\r\n'
head += b'Content-type: text/html\r\n'
head += b'\r\n'
return head
def make_body():
resp = b'<html>'
resp += b'<h1>Hello SSL</h1>'
resp += b'</html>'
return resp
( )
sock.setblocking(False)
sock.bind(('localhost' , 4433))
sock.listen(10)
sslctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
sslctx.load_cert_chain(certfile='./root-ca.crt',
keyfile='./root-ca.key')
loop.remove_reader(sock_fd)
loop.remove_writer(sock_fd)
waiter.set_result(None)
( )
while True:
conn, addr = await loop.sock_accept(sock)
conn.setblocking(False)
sslconn = sslctx.wrap_socket(conn,
server_side=True,
do_handshake_on_connect=False)
# wait SSL handshake
waiter = loop.create_future()
do_handshake(loop, sslconn, waiter)
await waiter
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(server(loop))
finally:
loop.close()
output:
# console 1
# console 2
$ curl https://localhost:4433 -v \
> --resolve localhost:4433:127.0.0.1 \
> --cacert ~/test/root-ca.crt
# ref: PEP333
import asyncio
import socket
import io
import sys
host = 'localhost'
port = 9527
(continues on next page)
( )
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.setblocking(False)
s.bind((host, port))
s.listen(10)
loop = asyncio.get_event_loop()
class WSGIServer(object):
# make header
resp = 'HTTP/1.1 {0}\r\n'.format(status)
(continues on next page)
( )
for header in resp_header:
resp += '{0}: {1}\r\n'.format(*header)
resp += '\r\n'
# make body
resp += '{0}'.format(data)
try:
await loop.sock_sendall(conn, str.encode(resp))
finally:
conn.close()
app = Flask(__name__)
@app.route('/hello')
def hello():
return Response("Hello WSGI",mimetype="text/plain")
Table of Contents
215
python-cheatsheet Documentation, 0.1.0
OK
>>> import unittest
>>> class TestFail(unittest.TestCase):
... def test_false(self):
... self.assertTrue(False)
...
>>> unittest.main()
F
======================================================================
FAIL: test_false (__main__.TestFail)
----------------------------------------------------------------------
Traceback (most recent call last):
File "<stdin>", line 3, in test_false
AssertionError: False is not true
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (failures=1)
import unittest
def fib(n):
return 1 if n<=2 else fib(n-1)+fib(n-2)
def setUpModule():
print("setup module")
def tearDownModule():
print("teardown module")
(continues on next page)
( )
class TestFib(unittest.TestCase):
def setUp(self):
print("setUp")
self.n = 10
def tearDown(self):
print("tearDown")
del self.n
@classmethod
def setUpClass(cls):
print("setUpClass")
@classmethod
def tearDownClass(cls):
print("tearDownClass")
def test_fib_assert_equal(self):
self.assertEqual(fib(self.n), 55)
def test_fib_assert_true(self):
self.assertTrue(fib(self.n) == 55)
if __name__ == "__main__":
unittest.main()
output:
$ python test.py
setup module
setUpClass
setUp
tearDown
.setUp
tearDown
.tearDownClass
teardown module
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
# test_module.py
from __future__ import print_function
import unittest
class TestFoo(unittest.TestCase):
@classmethod
def setUpClass(self):
print("foo setUpClass")
@classmethod
def tearDownClass(self):
print("foo tearDownClass")
(continues on next page)
( )
def setUp(self):
print("foo setUp")
def tearDown(self):
print("foo tearDown")
def test_foo(self):
self.assertTrue(True)
class TestBar(unittest.TestCase):
def setUp(self):
print("bar setUp")
def tearDown(self):
print("bar tearDown")
def test_bar(self):
self.assertTrue(True)
# test.py
from __future__ import print_function
def setUpModule():
print("setUpModule")
def tearDownModule():
print("tearDownModule")
if __name__ == "__main__":
test_module.setUpModule = setUpModule
test_module.tearDownModule = tearDownModule
suite1 = unittest.TestLoader().loadTestsFromTestCase(TestFoo)
suite2 = unittest.TestLoader().loadTestsFromTestCase(TestBar)
suite = unittest.TestSuite([suite1,suite2])
unittest.TextTestRunner().run(suite)
output:
$ python test.py
setUpModule
foo setUpClass
foo setUp
foo tearDown
.foo tearDownClass
bar setUp
bar tearDown
.tearDownModule
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
OK
>>> class TestRaiseFail(unittest.TestCase):
... def test_raise_fail(self):
... with self.assertRaises(SystemError):
... pass
>>> suite = unittest.TestLoader().loadTestsFromTestCase(TestRaiseFail)
>>> unittest.TextTestRunner(verbosity=2).run(suite)
test_raise_fail (__main__.TestRaiseFail) ... FAIL
======================================================================
FAIL: test_raise_fail (__main__.TestRaiseFail)
----------------------------------------------------------------------
Traceback (most recent call last):
File "<stdin>", line 4, in test_raise_fail
AssertionError: SystemError not raised
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (failures=1)
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
----------------------------------------------------------------------
Ran 4 tests in 0.000s
( )
OK
----------------------------------------------------------------------
Ran 2 tests in 0.001s
OK
----------------------------------------------------------------------
(continues on next page)
( )
Ran 4 tests in 0.000s
OK (skipped=3)
OK
<unittest.runner.TextTestResult run=1 errors=0 failures=0>
test_foo.py
import unittest
print(conf)
class TestFoo(unittest.TestCase):
def test_foo(self):
(continues on next page)
( )
print(conf)
test_bar.py
from __future__ import print_function
import unittest
import __builtin__
if __name__ == "__main__":
conf = type('TestConf', (object,), {})
conf.isskip = True
output:
$ python test_bar.py
<class '__main__.TestConf'>
test_foo (test_foo.TestFoo) ... <class '__main__.TestConf'>
ok
test_skip (test_foo.TestFoo) ... skipped 'skip test'
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK (skipped=1)
11.12. skip setup & teardown when the test is skipped 223
python-cheatsheet Documentation, 0.1.0
( )
test_not_skip (__main__.TestSkip) ... setUp
tearDown
ok
test_skip (__main__.TestSkip) ... skipped 'skip this test'
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK (skipped=1)
OK
<unittest.runner.TextTestResult run=1 errors=0 failures=0>
"""
This is an example of doctest
>>> fib(10)
55
"""
def fib(n):
""" This function calculate fib number.
Example:
( )
>>> fib(10)
55
>>> fib(-1)
Traceback (most recent call last):
...
ValueError
"""
if n < 0:
raise ValueError('')
return 1 if n<=2 else fib(n-1) + fib(n-2)
if __name__ == "__main__":
import doctest
doctest.testmod()
output:
$ python demo_doctest.py -v
Trying:
fib(10)
Expecting:
55
ok
Trying:
fib(10)
Expecting:
55
ok
Trying:
fib(-1)
Expecting:
Traceback (most recent call last):
...
ValueError
ok
2 items passed all tests:
1 tests in __main__
2 tests in __main__.fib
3 tests in 2 items.
3 passed and 0 failed.
Test passed.
import unittest
import doctest
"""
This is an example of doctest
>>> fib(10)
55
"""
( )
def fib(n):
""" This function calculate fib number.
Example:
>>> fib(10)
55
>>> fib(-1)
Traceback (most recent call last):
...
ValueError
"""
if n < 0:
raise ValueError('')
return 1 if n<=2 else fib(n-1) + fib(n-2)
if __name__ == "__main__":
finder = doctest.DocTestFinder()
suite = doctest.DocTestSuite(test_finder=finder)
unittest.TextTestRunner(verbosity=2).run(suite)
output:
fib (__main__)
Doctest: __main__.fib ... ok
----------------------------------------------------------------------
Ran 1 test in 0.023s
OK
OK = 'ok'
FAIL = 'fail'
ERROR = 'error'
SKIP = 'skip'
class JsonTestResult(TextTestResult):
( )
# TextTestResult has no successes attr
self.successes = []
def jsonify(self):
json_out = dict()
for t in self.successes:
json_out = self.json_append(t, OK, json_out)
for t, _ in self.failures:
json_out = self.json_append(t, FAIL, json_out)
for t, _ in self.errors:
json_out = self.json_append(t, ERROR, json_out)
for t, _ in self.skipped:
json_out = self.json_append(t, SKIP, json_out)
return json_out
class TestSimple(TestCase):
def test_ok_1(self):
foo = True
self.assertTrue(foo)
def test_ok_2(self):
bar = True
self.assertTrue(bar)
def test_fail(self):
baz = False
self.assertTrue(baz)
def test_raise(self):
raise RuntimeError
( )
@unittest.skip("Test skip")
def test_skip(self):
raise NotImplementedError
if __name__ == '__main__':
# redirector default output of unittest to /dev/null
with open(os.devnull, 'w') as null_stream:
# new a runner and overwrite resultclass of runner
runner = TextTestRunner(stream=null_stream)
runner.resultclass = JsonTestResult
# create a testsuite
suite = TestLoader().loadTestsFromTestCase(TestSimple)
output:
$ python test.py
{'TestSimple': {'error': ['test_raise'],
'fail': ['test_fail'],
'ok': ['test_ok_1', 'test_ok_2'],
'skip': ['test_skip']}}
# python-3.3 or above
>>> import os
>>> def test():
... try:
... os.remove('%$!?&*')
... except OSError as e:
... print(e)
... else:
... print('test success')
...
>>> test()
[Errno 2] No such file or directory: '%$!?&*'
PATH = '$@!%?&'
def fake_remove(path):
print("Fake remove")
class SimplePatch:
def __enter__(self):
orig, attr = self.get_target(self._target)
self.orig, self.attr = orig, attr
self.orig_attr = getattr(orig, attr)
setattr(orig, attr, self._new)
return self._new
( )
try:
os.remove(PATH)
except OSError as e:
print(e)
output:
$ python3 simple_patch.py
---> inside unittest.mock.patch scope
Fake remove
---> inside simple patch scope
Fake remove
---> outside patch scope
[Errno 2] No such file or directory: '$@!%?&'
Table of Contents
* C API source
* Prepare setup.py
* Build C API source
* Run the C module
– PyObject with Member and Methods
* C API source
* Compare performance with pure Python
// fib.c
unsigned int fib(unsigned int n)
(continues on next page)
231
python-cheatsheet Documentation, 0.1.0
( )
{
if ( n < 2) {
return n;
}
return fib(n-1) + fib(n-2);
}
import errno
import os
stat = libc.stat
class Stat(Structure):
'''
From /usr/include/sys/stat.h
struct stat {
(continues on next page)
( )
dev_t st_dev;
ino_t st_ino;
mode_t st_mode;
nlink_t st_nlink;
uid_t st_uid;
gid_t st_gid;
dev_t st_rdev;
#ifndef _POSIX_SOURCE
struct timespec st_atimespec;
struct timespec st_mtimespec;
struct timespec st_ctimespec;
#else
time_t st_atime;
long st_atimensec;
time_t st_mtime;
long st_mtimensec;
time_t st_ctime;
long st_ctimensec;
#endif
off_t st_size;
int64_t st_blocks;
u_int32_t st_blksize;
u_int32_t st_flags;
u_int32_t st_gen;
int32_t st_lspare;
int64_t st_qspare[2];
};
'''
_fields_ = [('st_dev', c_ulong),
('st_ino', c_ulong),
('st_mode', c_ushort),
('st_nlink', c_uint),
('st_uid', c_uint),
('st_gid', c_uint),
('st_rdev', c_ulong),
('st_atime', c_longlong),
('st_atimendesc', c_long),
('st_mtime', c_longlong),
('st_mtimendesc', c_long),
('st_ctime', c_longlong),
('st_ctimendesc', c_long),
('st_size', c_ulonglong),
('st_blocks', c_int64),
('st_blksize', c_uint32),
('st_flags', c_uint32),
('st_gen', c_uint32),
('st_lspare', c_int32),
('st_qspare', POINTER(c_int64) * 2)]
# stat success
path = create_string_buffer(b"/etc/passwd")
st = Stat()
ret = stat(path, byref(st))
assert ret == 0
( )
st = Stat()
ret = stat(path, byref(st))
if ret != 0:
errno_ = get_errno() # get errno
errmsg = "stat({}) failed. {}".format(path.raw, os.strerror(errno_))
raise OSError(errno_, errmsg)
output:
$ python err_handling.py # python2
Traceback (most recent call last):
File "err_handling.py", line 85, in <module>
raise OSError(errno_, errmsg)
OSError: [Errno 2] stat(&%$#@!) failed. No such file or directory
# from Linux/include/uapi/linux/magic.h
EXT_SUPER_MAGIC = 0x137D
EXT2_OLD_SUPER_MAGIC = 0xEF51
EXT2_SUPER_MAGIC = 0xEF53
EXT3_SUPER_MAGIC = 0xEF53
EXT4_SUPER_MAGIC = 0xEF53
BTRFS_SUPER_MAGIC = 0x9123683E
class KernelFsid(Structure):
'''
From Linux/arch/mips/include/asm/posix_types.h
typedef struct {
long val[2];
} __kernel_fsid_t;
'''
_fields_ = [('val', POINTER(c_long) * 2)]
class Statfs(Structure):
'''
(continues on next page)
( )
From Linux/arch/mips/include/asm/statfs.h
struct statfs {
long f_type;
#define f_fstyp f_type
long f_bsize;
long f_frsize;
long f_blocks;
long f_bfree;
long f_files;
long f_ffree;
long f_bavail;
/* Linux specials */
__kernel_fsid_t f_fsid;
long f_namelen;
long f_flags;
long f_spare[5];
};
'''
_fields_ = [('f_type', c_long),
('f_bsize', c_long),
('f_frsize', c_long),
('f_block', c_long),
('f_bfree', c_long),
('f_files', c_long),
('f_ffree', c_long),
('f_fsid', KernelFsid),
('f_namelen', c_long),
('f_flags', c_long),
('f_spare', POINTER(c_long) * 5)]
path = create_string_buffer(b'/etc')
fst = Statfs()
ret = statfs(path, byref(fst))
assert ret == 0
output:
$ python3 statfs.py
Is ext4? True
import os
import sys
(continues on next page)
( )
import errno
import platform
# check os
p = platform.system()
if p != "Linux":
raise OSError("Not support '{}'".format(p))
src = sys.argv[1]
dst = sys.argv[2]
src_size = os.stat(src).st_size
offset = c_int64(0)
output:
$ python3 sendfile.py /etc/resolv.conf resolve.conf; cat resolve.conf
nameserver 192.168.1.1
( )
#define _PyObject_HEAD_EXTRA \
struct _object *_ob_next;\
struct _object *_ob_prev;
#define PyObject_HEAD \
_PyObject_HEAD_EXTRA \
Py_ssize_t ob_refcnt;\
struct _typeobject *ob_type;
#include <Python.h>
typedef struct {
PyObject_HEAD
} spamObj;
( )
PyMODINIT_FUNC
initspam(void)
{
PyObject *m;
spamType.tp_new = PyType_GenericNew;
if (PyType_Ready(&spamType) < 0) {
goto END;
}
m = Py_InitModule3("spam", spam_methods, "Example of Module");
Py_INCREF(&spamType);
PyModule_AddObject(m, "spam", (PyObject *)&spamType);
END:
return;
}
setup(name="spam",
version="1.0",
ext_modules=[Extension("spam", ["spam.c"])])
#include <Python.h>
#include <structmember.h>
typedef struct {
PyObject_HEAD
PyObject *hello;
(continues on next page)
( )
PyObject *world;
int spam_id;
} spamObj;
static void
spamdealloc(spamObj *self)
{
Py_XDECREF(self->hello);
Py_XDECREF(self->world);
self->ob_type
->tp_free((PyObject*)self);
}
/* __new__ */
static PyObject *
spamNew(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
spamObj *self = NULL;
self = (spamObj *)
type->tp_alloc(type, 0);
if (self == NULL) {
goto END;
}
/* alloc str to hello */
self->hello =
PyString_FromString("");
if (self->hello == NULL)
{
Py_XDECREF(self);
self = NULL;
goto END;
}
/* alloc str to world */
self->world =
PyString_FromString("");
if (self->world == NULL)
{
Py_XDECREF(self);
self = NULL;
goto END;
}
self->spam_id = 0;
END:
return (PyObject *)self;
}
/* __init__ */
static int
spamInit(spamObj *self, PyObject *args, PyObject *kwds)
{
int ret = -1;
PyObject *hello=NULL,
*world=NULL,
*tmp=NULL;
( )
"hello",
"world",
"spam_id", NULL};
static long
fib(long n) {
if (n<=2) {
return 1;
}
return fib(n-1)+fib(n-2);
}
static PyObject *
spamFib(spamObj *self, PyObject *args)
{
PyObject *ret = NULL;
long arg = 0;
( )
{"hello", //name
T_OBJECT_EX, //type
offsetof(spamObj, hello), //offset
0, //flags
"spam hello"}, //doc
/* spamObj.world*/
{"world",
T_OBJECT_EX,
offsetof(spamObj, world),
0,
"spam world"},
/* spamObj.spam_id*/
{"spam_id",
T_INT,
offsetof(spamObj, spam_id),
0,
"spam id"},
/* Sentiel */
{NULL}
};
( )
Py_TPFLAGS_BASETYPE, //tp_flags
"spamKlass objects", //tp_doc
0, //tp_traverse
0, //tp_clear
0, //tp_richcompare
0, //tp_weaklistoffset
0, //tp_iter
0, //tp_iternext
spam_methods, //tp_methods
spam_members, //tp_members
0, //tp_getset
0, //tp_base
0, //tp_dict
0, //tp_descr_get
0, //tp_descr_set
0, //tp_dictoffset
(initproc)spamInit, //tp_init
0, //tp_alloc
spamNew, //tp_new
};
PyMODINIT_FUNC
initspam(void)
{
PyObject* m;
if (PyType_Ready(&spamKlass) < 0) {
goto END;
}
m = Py_InitModule3(
"spam", // Mod name
module_methods, // Mod methods
"Spam Module"); // Mod doc
if (m == NULL) {
goto END;
}
Py_INCREF(&spamKlass);
PyModule_AddObject(
m, // Module
"SpamKlass", // Class Name
(PyObject *) &spamKlass); // Class
END:
return;
}
Table of Contents
13.1 Decorator in C
Python
245
python-cheatsheet Documentation, 0.1.0
#include <stdio.h>
// Original function
void hello(char *str) {
printf("Hello %s\n", str);
}
( )
return 0;
}
output:
$ gcc example.c
$ ./a.out
I am decorator
Hello KerKer
I am decorator
add 1 + 2 = 3
Python
#include <stdio.h>
enum func_id{
FUNC_1,FUNC_2,FUNC_3
};
void func_1() {
printf("Hello ");
}
void func_2() {
printf("World ");
}
void func_3() {
(continues on next page)
( )
printf("!!!\n");
}
func gFuncTable[] = {
func_1,func_2,func_3
};
return 0;
}
13.3 Closure in C
Python
( )
>>> closure(9527)
9527
#include <stdio.h>
#include <stdlib.h>
return 0;
}
13.4 Generator
Python
#include <stdio.h>
#include <stdlib.h>
struct gen {
int (*next) (struct gen *);
int var;
};
( )
int next_func(struct gen *g) {
printf("var = %d\n",g->var);
g->var +=1;
return g->var;
}
Python
#include <stdio.h>
#include <stdlib.h>
#define ENTER(type,ptr,len) \
printf("enter context manager\n");\
ptr = malloc(sizeof(type)*len);\
if (NULL == ptr) { \
printf("malloc get error\n");\
goto exit;\
}\
#define EXIT(ptr) \
(continues on next page)
( )
exit:\
printf("exit context manager\n");\
if (NULL != ptr) {\
free(ptr);\
ptr = NULL; \
}\
13.6 Tuple in C
Python
>>> a = ("Hello","World",123)
>>> for _ in a: print _,
...
Hello World 123
#include <stdio.h>
Python
>>> import os
>>> def spam(a,b):
... try:
(continues on next page)
( )
... os.listdir('.')
... except OSError:
... print "listdir get error"
... return
... try:
... a/b
... except ZeroDivisionError:
... print "zero division"
... return
...
>>> spam(1,0)
zero division
# single exit -> using decorator
>>> import time
>>> def profile(func):
... def wrapper(*args, **kwargs):
... s = time.time()
... ret = func(*args, **kwargs)
... e = time.time()
... print e - s
... return ret
... return wrapper
...
>>> @profile
... def spam(a,b):
... try:
... os.listdir('.')
... except OSError:
... return
... try:
... a/b
... except ZeroDivisionError:
... return
...
>>> spam(1,0)
0.000284910202026
C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
( )
ptr = NULL;
}
return ret;
}
Python
>>> try:
... # do something...
... raise OSError
... except OSError as e:
... print('get error OSError')
... finally:
... print('finally block')
...
get error OSError
finally block
#include <stdio.h>
#include <string.h>
#include <setjmp.h>
enum {
ERR_EPERM = 1,
ERR_ENOENT,
ERR_ESRCH,
ERR_EINTR,
ERR_EIO
};
try {
raise(ERR_ENOENT);
} except(ERR_EPERM) {
printf("get exception: %s\n", strerror(ERR_EPERM));
ret = -1;
(continues on next page)
( )
} except(ERR_ENOENT) {
printf("get exception: %s\n", strerror(ERR_ENOENT));
ret = -1;
} except(ERR_ESRCH) {
printf("get exception: %s\n", strerror(ERR_ENOENT));
ret = -1;
} finally {
printf("finally block\n");
} end;
return ret;
}
Python
_registry = { }
_msg_queue = deque()
def actor(func):
def wrapper(*args, **kwargs):
gen = func(*args, **kwargs)
next(gen)
_registry[func.__name__] = gen
return wrapper
@actor
def ping():
""" coroutine ping """
n = yield
print('ping %d' % n)
send('pong', 20001)
n = yield
print('ping %d' % n)
send('pong', 20002)
@actor
def pong():
""" coroutine pong """
n = yield
print('pong %d' % n)
send('ping', 10001)
n = yield
print('pong %d' % n)
send('ping', 10002)
def run():
(continues on next page)
( )
while _msg_queue:
try:
name, msg = _msg_queue.popleft()
_registry[name].send(msg)
except StopIteration:
pass
ping()
pong()
send('ping', 10001)
run()
output:
$ python coro.py
ping 10001
pong 20001
ping 10001
pong 20002
C
#include <stdio.h>
#include <string.h>
#include <setjmp.h>
GEN_FUNC(ping) ();
GEN_FUNC(pong) ();
GEN_FUNC(ping) ()
{
int r = 0;
r = setjmp(jmp_ping);
if (r == 0) pong();
printf("ping %d\n", r);
( )
}
GEN_FUNC(pong) ()
{
int r = 0;
output:
$ ./a.out
ping 10001
pong 20001
ping 10002
pong 20002
Python
#include <stdio.h>
#define FUNC(...) \
base_func((struct input ){.var=0, ##__VA_ARGS__});
struct input {
char *str;
int var;
double dvar;
};
( )
void base_func(struct input in){
printf("str = %s, var = %d"
", dvar = %lf\n",
in.str, in.var,in.dvar);
}
Python
>>> x = [1,2,3,4,5]
>>> y = map(lambda x:2*x, x)
>>> print y
[2, 4, 6, 8, 10]
#or
>>> x = [1,2,3,4,5]
>>> y = [2*_ for _ in x]
>>> print y
[2, 4, 6, 8, 10]
#include <stdio.h>
int multi2(int a) {
return 2*a;
}
MAP(multi2, x, y, 5);
for(i=0;i<5;i++) {
printf("%d ",y[i]);
}
printf("\n");
}
13.12 foreach in C
Python
>>> x = ["Hello","World","!!!"]
>>> for _ in x:print _,
...
Hello World !!!
C
#include <stdio.h>
Python
# common declaration
>>> class obj(object):
... def __init__(self):
... self.a = 0
... self.b = 0
... def add(self):
... return self.a + self.b
... def sub(self):
... return self.a - self.b
...
>>> o = obj()
>>> o.a = 9527
>>> o.b = 5566
>>> o.add()
15093
>>> o.sub()
3961
# patch class (more like ooc)
>>> class obj(object):
... def __init__(self):
... self.a = 0
... self.b = 0
...
>>> def add(self):
... return self.a+self.b
(continues on next page)
( )
...
>>> def sub(self):
... return self.a - self.b
...
>>> obj.add = add
>>> obj.sub = sub
>>> o = obj()
>>> o.a = 9527
>>> o.b = 5566
>>> o.add()
15093
>>> o.sub()
3961
#include <stdio.h>
#include <stdlib.h>
struct object {
int a;
int b;
// virtual
func add;
func sub;
};
int add_func(Obj *self) {
return self->a + self->b;
}
int sub_func(Obj *self) {
return self->a - self->b;
}
int init_obj(Obj **self) {
*self = malloc(sizeof(Obj));
if (NULL == *self) {
return -1;
}
(*self)->a = 0;
(*self)->b = 0;
(*self)->add = add_func;
(*self)->sub = sub_func;
return 0;
}