
рдпрд╣ рдореЗрд░реЗ рдЯреЗрд▓реАрдЧреНрд░рд╛рдо-рдЪреИрдирд▓ @pythonetc рд╕реЗ рдкрд╛рдпрдерди рдФрд░ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реБрдЭрд╛рд╡реЛрдВ рдФрд░ рдЯреНрд░рд┐рдХреНрд╕ рдХрд╛ рдПрдХ рдирдпрд╛ рдЪрдпрди рд╣реИред
рдкрд┐рдЫрд▓реЗ рдкреНрд░рдХрд╛рд╢рди ред
рдиреЗрдЯрд╡рд░реНрдХ рдХреЛ рдмрд╛рдЗрдЯреНрд╕ рдХреЗ рд░реВрдк рдореЗрдВ рд╕реНрдЯреЛрд░ рдХрд░рдирд╛ рдФрд░ рднреЗрдЬрдирд╛ рдПрдХ рдмрд╣реБрдд рдмрдбрд╝рд╛ рд╡рд┐рд╖рдп рд╣реИред рдЖрдЗрдП рдХреБрдЫ рдЙрдкрдХрд░рдгреЛрдВ рдкрд░ рдЪрд░реНрдЪрд╛ рдХрд░реЗрдВ рдЬреЛ рдЖрдорддреМрд░ рдкрд░ рдкрд╛рдпрдерди рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ рдФрд░ рдЙрдирдХреЗ рдлрд╛рдпрджреЗ рдФрд░ рдиреБрдХрд╕рд╛рдиред
рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ рдореИрдВ рдЙрди рд╢рд╣рд░реЛрдВ рдХреА рд╡рд╕реНрддреБ рдХреЛ рдХреНрд░рдордмрджреНрдз рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реВрдБрдЧрд╛ рдЬрд┐рдирдореЗрдВ рдХреБрдЫ рд╢рд╣рд░ рдХреА рд╡рд╕реНрддреБрдУрдВ рдХреЗ рд╕рд╛рде-рд╕рд╛рде рдЙрдирдХреЗ рдХреНрд░рдо рднреА рд╢рд╛рдорд┐рд▓ рд╣реИрдВред рдпрд╣рд╛рдБ рдЪрд╛рд░ рд╡рд┐рдзрд┐ рд╣реИ рдЬрд┐рд╕рдХрд╛ рдЖрдк рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
1. JSONред рдпрд╣ рдорд╛рдирд╡ рдкрдардиреАрдп рд╣реИ, рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдореЗрдВ рдЖрд╕рд╛рди рд╣реИ, рд▓реЗрдХрд┐рди рдмрд╣реБрдд рдЕрдзрд┐рдХ рдореЗрдореЛрд░реА рдХрд╛ рдЙрдкрднреЛрдЧ рдХрд░рддрд╛ рд╣реИред рдпрд╣реА рдЕрдиреНрдп рд╕реНрд╡рд░реВрдкреЛрдВ рдЬреИрд╕реЗ рдХрд┐ YAML рдпрд╛ XML рдХреЗ рд▓рд┐рдП рднреА рд╕рд╣реА рд╣реИред
class City: def to_dict(self): return dict( name=self._name, country=self._country, lon=self._lon, lat=self._lat, ) class Cities: def __init__(self, cities): self._cities = cities def to_json(self): return json.dumps([ c.to_dict() for c in self._cities ]).encode('utf8')
2. рдЕрдЪрд╛рд░ред рдЕрдЪрд╛рд░ рдкрд╛рдпрдерди рдХреЗ рд▓рд┐рдП рдореВрд▓ рд╣реИ, рдЗрд╕реЗ JSON рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЕрдиреБрдХреВрд▓рд┐рдд рдФрд░ рдХрдо рдореЗрдореЛрд░реА рдХрд╛ рдЙрдкрднреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдирдХрд╛рд░рд╛рддреНрдордХ рдкрдХреНрд╖ рдпрд╣ рд╣реИ рдХрд┐ рдЖрдкрдХреЛ рдбреЗрдЯрд╛ рдХреЛ рдЕрдирдкрд┐рдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд╛рдпрдерди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред
class Cities: def pickle(self): return pickle.dumps(self)
3. рдкреНрд░реЛрдЯреЛрдмреЙрдлрд╝ (рдФрд░ рдЕрдиреНрдп рдмрд╛рдЗрдирд░реА рдзрд╛рд░рд╛рд╡рд╛рд╣рд┐рдХ рдЬреИрд╕реЗ рдХрд┐ рдореЗрд╕рдХрдк)ред рдХрдо рдореЗрдореЛрд░реА рдХрд╛ рдЙрдкрднреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдХрд┐рд╕реА рдЕрдиреНрдп рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛рдУрдВ рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХрд╕реНрдЯрдо рд╕реНрдХреАрдорд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ:
syntax = "proto2"; message City { required string name = 1; required string country = 2; required float lon = 3; required float lat = 4; } message Cities { repeated City cities = 1; } class City: def to_protobuf(self): result = city_pb2.City() result.name = self._name result.country = self._country result.lon = self._lon result.lat = self._lat return result class Cities: def to_protobuf(self): result = city_pb2.Cities() result.cities.extend([ c.to_protobuf() for c in self._cities ]) return result
4. рдореИрдиреБрдЕрд▓ред рдЖрдк рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдбреЗрдЯрд╛ рдФрд░ рд╕реНрдЯреНрд░рдХреНрдЪрд░ рдореЙрдбреНрдпреВрд▓ рдХреЗ рд╕рд╛рде рдбреЗрдЯрд╛ рдЕрдирдкреИрдХ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рдЖрдкрдХреЛ рд╕реНрдореГрддрд┐ рдХреА рдкреВрд░реНрдг рдиреНрдпреВрдирддрдо рдорд╛рддреНрд░рд╛ рдХрд╛ рдЙрдкрднреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рдВрд╕реНрдХрд░рдг рдФрд░ рд╕реНрдкрд╖реНрдЯ рд╕реНрдХреАрдорд╛рдУрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рд╕реЗ рдкреНрд░реЛрдЯреЛрдмреЙрдлрд╝ рдПрдХ рдмреЗрд╣рддрд░ рд╡рд┐рдХрд▓реНрдк рд╣реЛ рд╕рдХрддрд╛ рд╣реИред
class City: def to_bytes(self): name_encoded = self._name.encode('utf8') name_length = len(name_encoded) country_encoded = self._country.encode('utf8') country_length = len(country_encoded) return struct.pack( 'BsBsff', name_length, name_encoded, country_length, country_encoded, self._lon, self._lat, class Cities: def to_bytes(self): return b''.join( c.to_bytes() for c in self._cities )
рдпрджрд┐ рдХрд┐рд╕реА рдлрд╝рдВрдХреНрд╢рди рддрд░реНрдХ рдореЗрдВ рдХрд┐рд╕реА рдХрд╛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рди
None
рдФрд░ рдЙрд╕реЗ
T
рд░реВрдк рдореЗрдВ рдПрдиреЛрдЯреЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ
mypy
рд╕реНрд╡рддрдГ рдЗрд╕реЗ
Optional[T]
(рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ,
Union[T, None]
) рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рдирддрд╛ рд╣реИред
рдпрд╣ рдЕрдиреНрдп рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЖрдкрдХреЗ рдкрд╛рд╕
f(x: A = B())
рдЬреИрд╕рд╛ рдХреБрдЫ рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдпрд╣ рдПрдХ рдЪрд░ рдЕрд╕рд╛рдЗрдирдореЗрдВрдЯ рдХреЗ рд╕рд╛рде рднреА рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛
a: A = None
рддреНрд░реБрдЯрд┐ рдХрд╛ рдХрд╛рд░рдг
a: A = None
рд╣реЛрдЧрд╛ред
def f(x: int = None): reveal_type(x) def g(y: int = 'x'): reveal_type(y) z: int = None reveal_type(z) $ mypy test.py test.py:2: error: Revealed type is 'Union[builtins.int, None]' test.py:4: error: Incompatible default for argument "y" (default has type "str", argument has type "int") test.py:5: error: Revealed type is 'builtins.int' test.py:7: error: Incompatible types in assignment (expression has type "None", variable has type "int") test.py:8: error: Revealed type is 'builtins.int'
рдкрд╛рдпрдерди 3 рдореЗрдВ, рдПрдХ рдмрд╛рд░
except
рдХреЛ рдЫреЛрдбрд╝ рджреЗрдиреЗ рдХреЗ рдмрд╛рдж, рдЕрдкрд╡рд╛рджреЛрдВ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдЪрд░
locals()
рд╕реЗ рд╣рдЯрд╛ рджрд┐рдП рдЬрд╛рддреЗ
locals()
рднрд▓реЗ рд╣реА рд╡реЗ рдкрд╣рд▓реЗ рд╕реЗ рдореМрдЬреВрдж рд╣реЛрдВ:
>>> e = 2 >>> try: ... 1/0 ... except Exception as e: ... pass ... >>> e Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'e' is not defined
рдпрджрд┐ рдЖрдк рдЕрдкрд╡рд╛рдж рдХрд╛ рд╕рдВрджрд░реНрдн рд╕рд╣реЗрдЬрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рджреВрд╕рд░реЗ рдЪрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реЛрдЧрд╛:
>>> error = None >>> try: ... 1/0 ... except Exception as e: ... error = e ... >>> error ZeroDivisionError('division by zero',)
рдпрд╣ рдкрд╛рдпрдерди 2 рдХреЗ рд▓рд┐рдП рд╕рд╣реА рдирд╣реАрдВ рд╣реИред
рдЖрдкрдХреЗ рдкрд╛рд╕ рдЕрдкрдирд╛ рдЦреБрдж рдХрд╛
pypi
рднрдВрдбрд╛рд░ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдпрд╣ рдЖрдкрдХреЛ рдЕрдкрдиреА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рдЕрдВрджрд░ рдкреИрдХреЗрдЬ рдЬрд╛рд░реА рдХрд░рдиреЗ рджреЗрддрд╛ рд╣реИ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдкрд╛рдЗрдк рдХреЗ рд╕рд╛рде рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реИ рдЬреИрд╕реЗ рдХрд┐ рд╡реЗ рдирд┐рдпрдорд┐рдд рдкреИрдХреЗрдЬ рд╣реИрдВред
рдпрд╣ рдЙрд▓реНрд▓реЗрдЦрдиреАрдп рд╣реИ рдХрд┐ рдЖрдкрдХреЛ рдХреЛрдИ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕реЙрдлрд╝реНрдЯрд╡реЗрдпрд░ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдПрдХ рдирд┐рдпрдорд┐рдд http-рд╕рд░реНрд╡рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣рд╛рдБ рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдПред
рдЖрдЗрдП
pythonetc
рдирд╛рдо рдХрд╛ рдПрдХ рддреБрдЪреНрдЫ рдкреИрдХреЗрдЬ рд╣реИред
setup.py: from setuptools import setup, find_packages setup( name='pythonetc', version='1.0', packages=find_packages(), ) pythonetc.py: def ping(): return 'pong'
рдЪрд▓рд┐рдП рдЗрд╕реЗ ~ / pypi рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рдЬрд╛рд░реА рдХрд░рддреЗ рд╣реИрдВ:
$ python setup.py sdist bdist_wheel тАж $ mv dist ~/pypi/pythonetc
рдЕрдм рдЗрд╕реЗ
pypi.pushtaev.ru
рд╕рд╛рде
pypi.pushtaev.ru
рдбреЛрдореЗрди рдкрд░ рд╕рд░реНрд╡рд░ рдХрд░реЗрдВ:
$ cat /etc/nginx/sites-enabled/pypi server { listen 80; server_name pypi.pushtaev.ru; root /home/vadim/pypi; index index.html index.htm index.nginx-debian.html; location / { autoindex on; try_files $uri $uri/ =404; } }
рдЕрдм рдЗрд╕реЗ рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:
$ pip install -i http://pypi.pushtaev.ru --trusted-host pypi.pushtaev.ru pythonetc тАж Collecting pythonetc Downloading http://pypi.pushtaev.ru/pythonetc/pythonetc-1.0-py3-none-any.whl Installing collected packages: pythonetc Successfully installed pythonetc-1.0 $ python Python 3.7.0+ (heads/3.7:0964aac, Mar 29 2019, 00:40:55) [GCC 4.9.2] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import pythonetc >>> pythonetc.ping() 'pong'
рдЬрдм рдЖрдк рдПрдХ рд╣реА рдирд╛рдо рдХреЗ рд╕рд╛рде рд╕реНрдерд╛рдиреАрдп рдЪрд░ рдХреЗ рдмрд░рд╛рдмрд░ рд╕рднреА рдХреБрдВрдЬрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рд╢рдмреНрджрдХреЛрд╢ рдШреЛрд╖рд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛, рддреЛ рдпрд╣ рдЕрдХреНрд╕рд░ рд╣реЛрддрд╛ рд╣реИред рдХреБрдЫ рдЗрд╕ рддрд░рд╣:
dict( context=context, mode=mode, action_type=action_type, )
ECMAScript рдХреЗ рдкрд╛рд╕ рдРрд╕реЗ рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП рд╡рд╕реНрддреБ рд╢рд╛рдмреНрджрд┐рдХ рдХрд╛ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╣реИ (рдЗрд╕реЗ рдСрдмреНрдЬреЗрдХреНрдЯ рд▓рд┐рдЯрд░рд▓ рдкреНрд░реЙрдкрд░реНрдЯреА рд╡реИрд▓реНрдпреВ рд╢реЙрд░реНрдЯрд╣реИрдВрдб рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ):
> var a = 1; < undefined > var b = 2; < undefined > {a, b} < {a: 1, b: 2}
рдкрд╛рдпрдерди рдореЗрдВ рдПрдХ рд╕рдорд╛рди рд╕рд╣рд╛рдпрдХ рдмрдирд╛рдирд╛ рд╕рдВрднрд╡ рд╣реИ (рдЕрдлрд╕реЛрд╕, рдпрд╣ ECMAScript рдЕрдВрдХрди рдХреЗ рд░реВрдк рдореЗрдВ рднреА рдЙрддрдирд╛ рдЕрдЪреНрдЫрд╛ рдирд╣реАрдВ рджрд┐рдЦрддрд╛ рд╣реИ):
def shorthand_dict(lcls, names): return {k: lcls[k] for k in names} context = dict(user_id=42, user_ip='1.2.3.4') mode = 'force' action_type = 7 shorthand_dict(locals(), [ 'context', 'mode', 'action_type', ])
рдЖрдкрдХреЛ рдЖрд╢реНрдЪрд░реНрдп рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рд╣рдореЗрдВ рдкрд┐рдЫрд▓реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдПрдХ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ
locals()
рдХреЛ рдкрд╛рд╕ рдХреНрдпреЛрдВ рдХрд░рдирд╛ рд╣реИред рдХреНрдпрд╛ рдХреИрд▓реА рдореЗрдВ рдХреЙрд▓ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдХреЗ
locals
рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИ? рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдЖрдкрдХреЛ рд╕рдмрд╕реЗ
inpsect
рдореЙрдбреНрдпреВрд▓ рдХреЗ рд╕рд╛рде рдЧрдбрд╝рдмрдбрд╝ рдХрд░рдирд╛ рд╣реЛрдЧрд╛:
import inspect def shorthand_dict(names): lcls = inspect.currentframe().f_back.f_locals return {k: lcls[k] for k in names} context = dict(user_id=42, user_ip='1.2.3.4') mode = 'force' action_type = 7 shorthand_dict([ 'context', 'mode', 'action_type', ])
рдЖрдк рдЖрдЧреЗ рднреА рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ -
https://github.com/alexmojaki/sorcery :
from sorcery import dict_of dict_of(context, mode, action_type)