====== Python notes ======
===== Time zones =====
The best practice is to store the datetime in the DB as UTC. To use time-zone-aware datetime objects internally, and to translate them to the end user’s time zone. It avoids the problem with Daylight Saving Time (DST), the zones where the clock is moved in spring and autumn.
Libraries to work with time zones and UTC are [[http://pytz.sourceforge.net/|pytz]] and [[http://crsmithdev.com/arrow/|arrow]].
Python’s datetime.datetime objects have a ''tzinfo'' attribute that can be used to store time zone information, represented as an instance of a subclass of ''datetime.tzinfo''. When this attribute is set and describes an offset, a datetime object is **aware**. Otherwise, it’s **naive**.
You can use ''is_aware()'' and ''is_naive()'' to determine whether datetimes are aware or naive.
===== PYTHONPATH =====
Python does not add the current directory to sys.path, but rather the directory that the script is in. Add the project directory to either sys.path or $PYTHONPATH
$ export PYTHONPATH=$(pwd);python resources/manage_server.py
===== Pip tools =====
==== Pip ====
If you wanted to install a module using pip3:
python3 -m pip install --upgrade pip
python3 -m pip install jupyter
=== Behind a proxy ===
sudo pip --proxy http://web-proxy.mydomain.com install somepackage
=== Split requirements ===
You can have this in one base file:
# Django
Django==1.8.9
django-configurations==1.0
...
And this in another:
-r base.txt
# Mocking
mock==1.3.0
requests-mock==1.3.0
...
==== Pipenv ====
https://pipenv.readthedocs.io
''pipenv install'' create the required pipfiles.
''pipenv shell'' activate the virtualenv.
''pipenv run python manage.py runserver'' runs ''python manage.py runserver'' inside the virtualenv.
''pipenv --rm'' removes the virtual env.
''pipenv --python 3.6'' tell pipenv to use python 3.6
You can specify where to place the virtual environment with the environment variable ''WORKON_HOME'':
export WORKON_HOME=~/.venvs
To start a project using 3.7:
pipenv install --python 3.7
The generated **Pipfile.lock** declares all dependencies (and sub-dependencies) of your project, their latest available versions, and the current hashes for the downloaded files. This ensures repeatable, and most importantly deterministic, builds.
===== Advanced asyncio =====
For a basic use go to [[wiki2:python3#asyncio_package|asyncio package]].
A good video about advanced asyncio: https://youtu.be/sW76-pRkZk8
==== asyncio perks ====
You can store the function and call it later:
import asyncio
async def speak():
print('C')
await asyncio.sleep(3)
return 'D'
async def run():
will_speak = speak()
print('A')
print('B')
print(await will_speak)
loop = asyncio.get_event_loop()
loop.run_until_complete(run())
# Prints: A B C D
You can wait until all the co-routines are finished:
async def run():
f = []
for x in range(1, 6):
f.append(meow(x))
await asyncio.wait(f)
==== Testing ====
=== Mocking co-routines ===
from unittest.mock import AsyncMock
@pytest.fixture()
def mock_sum(mocker):
async_mock = AsyncMock()
mocker.patch('app.sum', side_effect=async_mock)
return async_mock
@pytest.mark.asyncio
async def test_sum(mock_sum):
mock_sum.return_value = 4
result = await app.sum(1, 2)
assert result == 4
==== asyncio on Django ====
=== django-simple-task package ===
* https://pypi.org/project/django-simple-task/
from django_simple_task import defer
def task1():
time.sleep(1)
print("task1 done")
async def task2():
await asyncio.sleep(1)
print("task2 done")
def view(requests):
defer(task1)
defer(task2)
return HttpResponse(b"My View")
==== Libraries ====
* [[https://docs.aiohttp.org/en/stable/|AIOHTTP]], a ''requests'' async alternative.
===== Black =====
Launch black for those .py file which are gonna be commited:
git diff --name-only | grep ".py$" | xargs black
===== Notes =====
==== Install a new version of python ====
To install a new version of python do:
sudo apt-get install python3.8 python3.8-dev python3.8-distutils python3.8-venv
==== try\except\finally perks ====
This code...
def should_rise(flag):
if flag:
raise Exception()
def my_function(flag):
try:
should_rise(flag)
print("1")
return "1"
except:
print("2")
return "2"
finally:
print("3")
return "3"
print("f", my_function(False))
print("---")
print("f", my_function(True))
Prints:
1
3
f 3
---
2
3
f 3
==== Install package for the user ====
pip install --user mypy
Executables are found in ''~/.local/bin'' so you can do the next:
export PATH="$PATH:$HOME/.poetry/bin:$HOME/bin:$HOME/.local/bin"