ΠΠΎΠ±ΡΡ Π΄Π΅Π½ Π½Π° Π²ΡΠΈΡΠΊΠΈ!
29 ΡΠ΅Π²ΡΡΠ°ΡΠΈ 2020 Π³ΠΎΠ΄ΠΈΠ½Π° ΡΠ΅ ΡΡΡΡΠΎΡ ΠΎΡΠΈΡΠΈΠ°Π»Π΅Π½ ΠΌΠΈΠΊΡΠΎ-ΡΠ΅Π»ΠΈΠ· Π½Π° Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈΡΠ΅ smart-env ΠΈ python-shell. ΠΠ° ΡΠ΅Π·ΠΈ, ΠΊΠΎΠΈΡΠΎ Π½Π΅ ΡΠ° Π² ΡΠ΅ΡΠ΅Π½ΠΈΠ΅, ΠΏΡΠ΅Π΄Π»Π°Π³Π°ΠΌ ΠΏΡΠ΅Π΄Π²Π°ΡΠΈΡΠ΅Π»Π½ΠΎ Π΄Π° ΠΏΡΠΎΡΠ΅ΡΠ°Ρ .
Π ΠΊΡΠ°ΡΡΠ΅, ΡΡΠ΅Π΄ ΠΏΡΠΎΠΌΠ΅Π½ΠΈΡΠ΅ ΡΠ° β Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ½ΠΎ Π΄ΠΎΠΏΡΠ»Π²Π°Π½Π΅ Π½Π° ΠΊΠΎΠΌΠ°Π½Π΄ΠΈ, ΡΠ°Π·ΡΠΈΡΡΠ²Π°Π½Π΅ Π½Π° Π²ΡΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΠΈΡΠ΅ Π·Π° ΠΈΠ·ΠΏΡΠ»Π½Π΅Π½ΠΈΠ΅ Π½Π° ΠΊΠΎΠΌΠ°Π½Π΄ΠΈ, ΠΌΠ°Π»ΠΊΠΎ ΡΠ΅ΡΠ°ΠΊΡΠΎΡΠΈΠ½Π³ ΠΈ ΠΎΡΡΡΡΠ°Π½ΡΠ²Π°Π½Π΅ Π½Π° Π³ΡΠ΅ΡΠΊΠΈ.
ΠΠ° ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎΡΡΠΈ ΠΌΠΎΠ»Ρ ΠΏΠΎΠ΄ ΠΊΠ°Ρ.
ΠΠ°ΠΊΠ²ΠΎ Π½ΠΎΠ²ΠΎ Π² python-shell?
Π©Π΅ Π·Π°ΠΏΠΎΡΠ½Π° Π½Π°ΠΏΡΠ°Π²ΠΎ Ρ Π΄Π΅ΡΠ΅ΡΡΠ°.
ΠΠ²ΡΠΎΠ΄ΠΎΠ²ΡΡΡΠ²Π°Π½Π΅ Π½Π° ΠΊΠΎΠΌΠ°Π½Π΄ΠΈ
Π‘ΡΠ³Π»Π°ΡΠ΅ΡΠ΅ ΡΠ΅ β ΡΠ΄ΠΎΠ±Π½ΠΎ Π΅, ΠΊΠΎΠ³Π°ΡΠΎ ΡΠ΅Π΄Π°ΠΊΡΠΎΡ/IDE/ΡΠ΅ΡΠΌΠΈΠ½Π°Π» ΠΏΠΎΠ΄ΡΠΊΠ°Π·Π²Π° ΠΈΠΌΠ΅ΡΠΎ Π½Π° ΠΊΠΎΠΌΠ°Π½Π΄Π°ΡΠ°, Π° ΠΏΠΎΠ½ΡΠΊΠΎΠ³Π° ΠΈ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠΈΡΠ΅ Π·Π° ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½Π΅? ΠΡΠΎ ΠΈ python-shell ΠΏΠΎΡΡΡΠΏΠ²Π° ΠΏΠΎΡΡΠ΅ΠΏΠ΅Π½Π½ΠΎ Π² ΠΎΡΠΈΠ³ΡΡΡΠ²Π°Π½Π΅ΡΠΎ Π½Π° ΠΏΠΎΠ΄ΠΎΠ±Π½Π° ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π»Π½ΠΎΡΡ. ΠΠΎΡΠ°Π΄ΠΈ ΡΠ°ΠΊΡΠ°, ΡΠ΅ ΠΏΠΎΠ»Π΅ΡΠ°ΡΠ° Π½Π° ΠΊΠ»Π°ΡΠ° Shell Π² Π΄ΡΠ½ΠΎΡΠΎ Π΄Π΅ ΡΠ°ΠΊΡΠΎ Π½Π΅ ΡΠ° Π½Π΅Π³ΠΎΠ²ΠΈ ΠΏΠΎΠ»Π΅ΡΠ° (Π²Π΅Π·Π΄Π΅ΡΡΡΠΈΡ __getattr__), Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ½ΠΎΡΠΎ Π΄ΠΎΠΏΡΠ»Π²Π°Π½Π΅ Π΅ ΡΡΠ·Π΄Π°Π΄Π΅Π½ΠΎ ΡΡΡΠΎ ΠΎΡ Π½ΡΠ»Π° (ΡΡΠ΅Π· ΠΏΡΠ΅Π·Π°ΡΠ΅ΠΆΠ΄Π°Π½Π΅ Π½Π° ΠΌΠ΅ΡΠΎΠ΄Π° __dir__). Π ΠΌΠΎΠΌΠ΅Π½ΡΠ° Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ½ΠΎΡΠΎ Π΄ΠΎΠΏΡΠ»Π²Π°Π½Π΅ ΡΠ°Π±ΠΎΡΠΈ Π² ΡΡΠ΅Π΄ΠΈΡΠ΅ BPython ΠΈ IPython. Π Π°Π·Π±ΠΈΡΠ° ΡΠ΅, Π±ΠΈΡ ΠΈΡΠΊΠ°Π» Π΄Π° Π²ΠΈΠ΄Ρ ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡ Ρ ΠΏΠΎ-ΠΏΠΎΠΏΡΠ»ΡΡΠ½ΠΈ ΠΏΡΠΎΠ΄ΡΠΊΡΠΈ ΠΊΠ°ΡΠΎ PyCharm, ΠΈ Π² ΡΠ°Π·ΠΈ ΠΏΠΎΡΠΎΠΊΠ° ΡΠ΅ ΠΈΠ·ΡΡΠ°Π²Π°Ρ Π²ΡΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΠΈΡΠ΅ Π·Π° ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ.
ΠΠΎΠ±Π°Π²ΡΠ½Π΅ Π½Π° ΡΠ²ΠΎΠΉΡΡΠ²Π°
Π ΡΠ°ΠΌΠΊΠΈΡΠ΅ Π½Π° ΡΠ΅Π»ΠΈΠ·Π° ΠΊΠ»Π°ΡΡΡ Shell ΠΏΠΎΠ»ΡΡΠΈ Π½ΠΎΠ²ΠΎ ΡΠ²ΠΎΠΉΡΡΠ²ΠΎ last_command. ΠΡΠΆΠ΄Π°ΡΠ° ΠΎΡ Π½Π΅Π³ΠΎ Π²ΡΠ·Π½ΠΈΠΊΠ½Π°, ΡΡΠΉ ΠΊΠ°ΡΠΎ ΠΏΡΠΈ Π³Π΅Π½Π΅ΡΠΈΡΠ°Π½Π΅ Π½Π° ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ ShellException ΠΊΠΎΠΌΠ°Π½Π΄Π°ΡΠ° Ρ Π½Π΅Π½ΡΠ»Π΅Π² ΠΊΠΎΠ΄ Π½Π° Π²ΡΡΡΠ°Π½Π΅ ΠΎΠ±Π΅ΠΊΡ Command Π½Π΅ ΡΠ΅ Π²ΡΡΡΠ°ΡΠ΅ ΠΎΡ ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½Π΅ΡΠΎ Π½Π° __call__() Π½Π° ΠΎΠ±Π΅ΠΊΡΠ° Π½Π° ΠΊΠΎΠΌΠ°Π½Π΄Π°ΡΠ°. Π‘Π΅Π³Π° ΠΎΠ±Π°ΡΠ΅ Π΅ Π²ΡΠ·ΠΌΠΎΠΆΠ½ΠΎ Π΄Π° Π½Π°ΠΏΡΠ°Π²ΠΈΡΠ΅ ΡΠ»Π΅Π΄Π½ΠΎΡΠΎ:
try:
command = Shell.touch('/foo.txt')
except ShellException:
command = Shell.last_commandΠ‘ΠΏΠΈΡΡΠΊΡΡ Π½Π° ΡΠ²ΠΎΠΉΡΡΠ²Π°ΡΠ° Π½Π° ΠΎΠ±Π΅ΠΊΡΠ° Command ΡΡΡΠΎ ΡΠ΅ ΡΠ°Π·ΡΠΈΡΠΈ. ΠΠΎΠ±Π°Π²Π΅Π½ΠΎ Π΅ ΠΏΠΎΠ»Π΅ errors, ΠΊΠΎΠ΅ΡΠΎ Π²ΡΡΡΠ° ΠΈΠ·Ρ ΠΎΠ΄Π° Π½Π° ΠΊΠΎΠΌΠ°Π½Π΄Π°ΡΠ° Π² ΠΏΠΎΡΠΎΠΊΠ° Π·Π° Π³ΡΠ΅ΡΠΊΠΈ.
ΠΠ·ΠΏΡΠ»Π½Π΅Π½ΠΈΠ΅ Π½Π° ΠΊΠΎΠΌΠ°Π½Π΄ΠΈ Ρ Π½Π΅Π²Π°Π»ΠΈΠ΄Π½ΠΈ ΠΈΠΌΠ΅Π½Π° Π·Π° Python
ΠΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈ Π²ΡΠ² Π²ΡΡΠΊΠ° ΡΠΈΡΡΠ΅ΠΌΠ° ΠΈΠΌΠ° ΠΏΠΎΠ½Π΅ Π΅Π΄Π½Π° ΠΏΡΠΎΠ³ΡΠ°ΠΌΠ°, ΡΠΈΠ΅ΡΠΎ ΠΈΠΌΠ΅ Π½Π΅ Π΅ ΠΏΠΎΠ΄Ρ ΠΎΠ΄ΡΡΠΎ Π·Π° ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ Π² Python (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΈΠ·Π²Π΅ΡΡΠ½Π°ΡΠ° ΡΡΠΈΠ»ΠΈΡΠ° 2to3). ΠΠ΅ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° Ρ ΠΈΠ·Π²ΠΈΠΊΠ°ΡΠ΅ Ρ
Shell.2to3() Π½ΡΠΌΠ° Π΄Π° ΡΡΠ°Π±ΠΎΡΠΈ β ΠΈΠ½ΡΠ΅ΡΠΏΡΠ΅ΡΠ°ΡΠΎΡΡΡ Π½ΡΠΌΠ° Π΄Π° Ρ ΠΏΡΠΈΠ΅ΠΌΠ΅.
Π Π΅ΡΠ΅Π½ΠΈΠ΅ΡΠΎ Π΅ Π΄Π° ΡΠ΅ ΠΈΠ·Π²ΠΈΠΊΠ° ΠΊΠΎΠΌΠ°Π½Π΄Π°ΡΠ° ΠΏΠΎ Π·Π°ΠΎΠ±ΠΈΠΊΠΎΠ»Π΅Π½ Π½Π°ΡΠΈΠ½:
Shell("2to3") # Π²ΡΡΡΠ° ΠΎΠ±Π΅ΠΊΡ Π½Π° ΠΊΠΎΠΌΠ°Π½Π΄Π°ΡΠ°Π‘ΡΡΡΠ²Π° ΡΠΈ Π΄Π° ΡΠ΅ ΠΎΡΠ±Π΅Π»Π΅ΠΆΠΈ, ΡΠ΅ ΠΏΠΎ ΡΡΡΠΈΡ Π½Π°ΡΠΈΠ½ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΡΡΠ°ΡΡΠΈΡΠ°ΡΠ΅ ΠΈ Π²Π°Π»ΠΈΠ΄Π½ΠΈ ΠΊΠΎΠΌΠ°Π½Π΄ΠΈ ΠΎΡ Π³Π»Π΅Π΄Π½Π° ΡΠΎΡΠΊΠ° Π½Π° ΠΈΠ½ΡΠ΅ΡΠΏΡΠ΅ΡΠ°ΡΠΎΡΠ°, ΠΊΠΎΠ΅ΡΠΎ ΠΎΡΡΠ°Π²Ρ Π²ΡΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ Π΄Π° ΠΏΡΠ°Π²ΠΈΡΠ΅ Π³ΡΠ²ΠΊΠ°Π²ΠΈ ΡΠΊΡΠΈΠΏΡΠΎΠ²Π΅ ΠΊΠ°ΡΠΎ
cmd = "python{}".format(sys.version_info[0])
Shell(cmd)(*args, **kwargs)ΠΠ°Π»ΠΊΠΈ ΠΏΡΠΎΠΌΠ΅Π½ΠΈ
- Π Π΅Π°Π»ΠΈΠ·ΠΈΡΠ°Π½ΠΈ ΡΠ° ΠΌΠ΅ΡΠΎΠ΄ΠΈ __repr__() ΠΈ __str__() Π½Π° ΠΎΠ±Π΅ΠΊΡΠ° ΠΎΡ ΠΊΠ»Π°ΡΠ° Command, ΠΊΠΎΠΈΡΠΎ ΡΠ΅Π³Π° Π΄Π°Π²Π°Ρ ΠΈΠ½ΡΡΠΈΡΠΈΠ²Π½ΠΎ ΡΠ°Π·Π±ΠΈΡΠ°Π΅ΠΌΠΈ ΡΡΠΎΠΉΠ½ΠΎΡΡΠΈ (ΠΊΠΎΠΌΠ°Π½Π΄Π°ΡΠ° Ρ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠΈ ΠΈ Π½Π΅ΠΉΠ½ΠΈΡ stdout ΠΈΠ·Ρ ΠΎΠ΄ ΡΡΠΎΡΠ²Π΅ΡΠ½ΠΎ).
- ΠΠ°Π»ΠΊΠΈ ΠΊΠΎΡΠ΅ΠΊΡΠΈΠΈ ΠΏΠΎ ΠΊΠΎΠ΄Π°.
- ΠΠΎΠ±Π°Π²ΡΠ½Π΅ Π½Π° ΡΠ΅ΡΡΠΎΠ²ΠΎ ΠΏΠΎΠΊΡΠΈΡΠΈΠ΅ ΠΈ ΡΠ΅ΠΎΡΠ³Π°Π½ΠΈΠ·Π°ΡΠΈΡ Π½Π° ΡΡΡΠ΅ΡΡΠ²ΡΠ²Π°ΡΠΈΡΠ΅.
- ΠΠΎΠ±Π°Π²ΡΠ½Π΅ Π½Π° ΠΊΠ»Π°ΡΠΎΠ²Π΅ Subprocess ΠΈ Process, ΡΠΈΡΡΠΎ ΡΠ΅Π» Π΅ Π΄Π° ΡΡΠ·Π΄Π°Π΄Π°Ρ Π΄ΠΎΠΏΡΠ»Π½ΠΈΡΠ΅Π»Π½ΠΎ Π½ΠΈΠ²ΠΎ Π½Π° Π°Π±ΡΡΡΠ°ΠΊΡΠΈΡ ΠΏΡΠΈ ΡΠ°Π±ΠΎΡΠ° Ρ ΠΌΠΎΠ΄ΡΠ»Π° subprocess. Π ΠΏΠΎΠ²Π΅ΡΠ΅ΡΠΎ ΡΠ»ΡΡΠ°ΠΈ ΡΠΎΠ²Π° Π΅ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ Π·Π° ΠΎΡΡΡΡΠ°Π½ΡΠ²Π°Π½Π΅ Π½Π° ΠΏΠΎΠ²ΡΠΎΡΠ΅Π½ΠΈΡ Π² ΠΊΠΎΠ΄Π° ΠΏΡΠΈ ΡΠ°Π±ΠΎΡΠ° Ρ Python 2/3, Π½ΠΎ ΠΏΠΎΡΠ΅Π½ΡΠΈΠ°Π»Π½ΠΎ ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΏΡΠ΅Π΄Π»ΠΎΠΆΠΈ ΠΈ Π΄ΡΡΠ³ΠΈ ΠΏΡΠ΅Π΄ΠΈΠΌΡΡΠ²Π°.
ΠΠ°ΠΊΠ²ΠΎ Π΅ Π½ΠΎΠ²ΠΎΡΠΎ Π² smart-env?
Π ΡΡΠ°Π²Π½Π΅Π½ΠΈΠ΅ Ρ python-shell, Π² Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ°ΡΠ° smart-env ΠΏΡΠΎΠΌΠ΅Π½ΠΈΡΠ΅ ΡΠ° ΠΏΠΎ-ΠΌΠ°Π»ΠΊΠΎ. ΠΡΠΈΡΠΈΠ½Π°ΡΠ° Π΅ ΠΏΡΠΎΡΡΠ° - Π»ΠΈΠΏΡΠ°ΡΠ° Π½Π° ΡΠ²ΠΎΠ±ΠΎΠ΄Π½ΠΎ Π²ΡΠ΅ΠΌΠ΅, ΠΏΠΎΡΠ°Π΄ΠΈ ΠΊΠΎΠ΅ΡΠΎ Π½ΡΠΊΠΎΠΈ ΠΏΠΎΡΠ΅Π½ΡΠΈΠ°Π»Π½ΠΈ ΠΏΠΎΠ΄ΠΎΠ±ΡΠ΅Π½ΠΈΡ (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ½ΠΎ Π΄ΠΎΠΏΡΠ»Π²Π°Π½Π΅ Π½Π° ΠΏΡΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ Π½Π° ΡΡΠ΅Π΄Π°ΡΠ°) Π±ΡΡ Π° ΠΎΡΠ»ΠΎΠΆΠ΅Π½ΠΈ Π·Π° ΡΠ»Π΅Π΄Π²Π°ΡΠΎΡΠΎ ΠΈΠ·Π΄Π°Π½ΠΈΠ΅.
ΠΡΡΡΠ½ΠΎΡΡ, Π² Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ°ΡΠ° ΡΠ° Π½Π°ΠΏΡΠ°Π²Π΅Π½ΠΈ ΡΠ»Π΅Π΄Π½ΠΈΡΠ΅ ΠΏΡΠΎΠΌΠ΅Π½ΠΈ:
- ΠΠ°Π»ΠΊΠΈ ΠΊΠΎΡΠ΅ΠΊΡΠΈΠΈ ΠΏΠΎ ΠΊΠΎΠ΄Π°.
- Π Π΅ΡΠ°ΠΊΡΠΎΡΠΈΠ½Π³.
- Π Π΅ΠΎΡΠ³Π°Π½ΠΈΠ·Π°ΡΠΈΡ ΠΈ Π΄ΠΎΡΠ°Π±ΠΎΡΠΊΠ° Π½Π° ΡΡΡΠ΅ΡΡΠ²ΡΠ²Π°ΡΠΈΡΠ΅ ΡΠ΅ΡΡΠΎΠ²Π΅.
ΠΠ»Π°Π½ΠΎΠ²Π΅ Π·Π° ΡΠ»Π΅Π΄Π²Π°ΡΠΈΡΠ΅ ΠΈΠ·Π΄Π°Π½ΠΈΡ
ΠΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ°ΡΠ° python-shell
- ΠΠΎΠ±Π°Π²ΡΠ½Π΅ Π½Π° ΠΏΠΎΠ΄Π΄ΡΡΠΆΠΊΠ° Π·Π° Π½Π΅Π±Π»ΠΎΠΊΠΈΡΠ°ΡΠΈ ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½ΠΈΡ Π½Π° ΠΊΠΎΠΌΠ°Π½Π΄ΠΈ (ΠΏΠ°ΡΠ°Π»Π΅Π»ΠΈΠ·Π°ΡΠΈΡ Π½Π° ΠΈΠ·ΠΏΡΠ»Π½Π΅Π½ΠΈΠ΅ΡΠΎ).
ΠΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ° smart-env
- Π Π΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ Π½Π° Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ½ΠΎ Π΄ΠΎΠΏΡΠ»Π²Π°Π½Π΅ Π½Π° ΠΏΡΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ Π½Π° ΡΡΠ΅Π΄Π°ΡΠ° Π² ΠΊΠ»Π°ΡΠ° ENV.
- ΠΠΎΠ΄Π΄ΡΡΠΆΠΊΠ° Π½Π° ΠΎΠΏΠ΅ΡΠ°ΡΠΎΡΠ° in Π·Π° ΠΏΡΠΎΠ²Π΅ΡΠΊΠ° Π½Π° ΡΡΡΠ΅ΡΡΠ²ΡΠ²Π°Π½Π΅ΡΠΎ Π½Π° env-ΠΏΡΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ.
- Π Π΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ Π½Π° ΠΏΠΎΠ΄Π΄ΡΡΠΆΠΊΠ° Π·Π° ΡΡΠ½ΠΊΡΠΈΠΈΡΠ΅ str() ΠΈ repr() Π·Π° ΠΊΠ»Π°ΡΠ° ENV.
ΠΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ Π·Π° Π΄Π°ΡΠΈΡΠ΅ Π½Π° ΡΠ»Π΅Π΄Π²Π°ΡΠΈΡΠ΅ ΠΈΠ·Π΄Π°Π½ΠΈΡ ΡΠ΅ Π±ΡΠ΄Π΅ Π΄ΠΎΠΏΡΠ»Π½ΠΈΡΠ΅Π»Π½ΠΎ ΠΎΠ±ΡΠ²Π΅Π½Π° Π² ΡΠ»Π΅Π΄Π½ΠΈΡΠ΅ ΠΊΠΎΠΌΡΠ½ΠΈΠΊΠ°ΡΠΈΠΎΠ½Π½ΠΈ ΠΊΠ°Π½Π°Π»ΠΈ:
- ΠΠΊΡΡΠ°Π»ΠΈΠ·Π°ΡΠΈΡ Π² ΡΠ°Π·ΠΈ ΡΡΠ°ΡΠΈΡ.
ΠΠ·ΡΠΎΡΠ½ΠΈΠΊ: habr.com
