18.1. Modules Stdlib
Python Standard Library
pprint
random
datetime + zoneinfo
pathlib
logging
json
csv
itertools
re
dataclasses
doctest
unittest
18.1.1. PPrint
SetUp:
>>> from pprint import pprint
Pretty print:
>>> data = [[1,2,3], [4,5,6], [7,8,9]]
>>>
>>> pprint(data, width=20, sort_dicts=False)
[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
18.1.2. Random
SetUp:
>>> from random import random, randint, choice, shuffle, sample, seed
>>> seed(0)
Generate random float between 0.0 and 1.0:
>>> random()
0.8444218515250481
Generate random integer between a and b (both ends inclusive):
>>> randint(0, 10)
6
Select k elements from data:
>>> data = ['red', 'green', 'blue']
>>>
>>> sample(data, k=2)
['red', 'green']
Select one from data:
>>> data = ['red', 'green', 'blue']
>>>
>>> choice(data)
'blue'
Shuffle data:
>>> data = ['red', 'green', 'blue']
>>>
>>> shuffle(data)
>>> print(data)
['red', 'blue', 'green']
18.1.3. Datetime
SetUp:
>>> from datetime import date, time, datetime, timezone, timedelta
>>> from zoneinfo import ZoneInfo
Create objects:
>>> d = date(2000, 1, 1)
>>> t = time(1, 2, 3, 4)
>>> dt = datetime(2000, 1, 1, 1, 2, 3, 4)
Get date and time from datetime:
>>> dt = datetime(2000, 1, 1, 1, 2, 3, 4)
>>>
>>> dt.date()
datetime.date(2000, 1, 1)
>>>
>>> dt.time()
datetime.time(1, 2, 3, 4)
Get parts from datetime:
>>> dt = datetime(2000, 1, 1, 1, 2, 3, 4)
>>>
>>> dt.year
2000
>>> dt.month
1
>>> dt.day
1
>>> dt.hour
1
>>> dt.minute
2
>>> dt.second
3
>>> dt.microsecond
4
Current date and time in local timezone:
>>> date.today()
datetime.date(2000, 1, 1)
>>>
>>> datetime.now()
datetime.datetime(2000, 1, 1, 0, 1, 2, 3)
Current date and time with timezone information:
>>> datetime.now(timezone.utc)
datetime.datetime(2000, 1, 1, 0, 1, 2, 3, tzinfo=datetime.timezone.utc)
>>>
>>> datetime.now(ZoneInfo('UTC'))
datetime.datetime(2000, 1, 1, 0, 1, 2, 3, tzinfo=zoneinfo.ZoneInfo(key='UTC'))
>>>
>>> datetime.now(ZoneInfo('Europe/Warsaw'))
datetime.datetime(2000, 1, 1, 1, 1, 2, 3, tzinfo=zoneinfo.ZoneInfo(key='Europe/Warsaw'))
Convert timezones:
>>> dt = datetime(2000, 1, 1, 0, 1, 2, 3, tzinfo=ZoneInfo('UTC'))
>>>
>>> dt.astimezone(ZoneInfo('Europe/Warsaw'))
datetime.datetime(2000, 1, 1, 1, 1, 2, 3, tzinfo=zoneinfo.ZoneInfo(key='Europe/Warsaw'))
Date offset:
>>> date(2000, 1, 1) + timedelta(days=4)
datetime.date(2000, 1, 5)
Date difference:
>>> a = date(2000, 1, 1)
>>> b = date(2025, 1, 1)
>>>
>>> diff = (b - a)
>>> years = diff.days / 365.25
>>> round(years)
25
Format date:
>>> dt = datetime(2000, 1, 1, 0, 1, 2, 3)
>>>
>>> dt.strftime('%Y-%m-%d')
'2000-01-01'
>>>
>>> dt.strftime('%Y-%m-%d %H:%M:%S')
'2000-01-01 00:01:02'
>>>
>>> dt.strftime('%Y-%m-%d %H:%M:%S %a %A %b %B')
'2000-01-01 00:01:02 Sat Saturday Jan January'
Parse date:
>>> text = '2000-01-01 00:01:02'
>>>
>>> datetime.strptime(text, '%Y-%m-%d %H:%M:%S')
datetime.datetime(2000, 1, 1, 0, 1, 2)
ISO-8601:
>>> dt = datetime(2000, 1, 1, 0, 1, 2, 3)
>>> dt.isoformat()
'2000-01-01T00:01:02.000003'
>>>
>>> text = '2000-01-01 00:01:02'
>>> datetime.fromisoformat(text)
datetime.datetime(2000, 1, 1, 0, 1, 2)
Timestamp:
>>> dt = datetime(2000, 1, 1, 0, 1, 2, 3)
>>> dt.timestamp()
946681262.000003
>>>
>>> datetime.fromtimestamp(946681262.000003)
datetime.datetime(2000, 1, 1, 0, 1, 2, 3)
18.1.4. Pathlib
SetUp:
>>> from pathlib import Path
Current directory:
>>> current = Path.cwd()
>>> current
PosixPath('/tmp/')
Check:
>>> mydir = Path('/tmp')
>>>
>>> current.exists()
True
>>>
>>> current.is_file()
False
>>>
>>> current.is_dir()
True
Directory:
>>> mydir = Path('/tmp/mydir')
>>>
>>> mydir.mkdir(parents=True, exist_ok=True)
>>>
>>> mydir.rmdir()
File:
>>> myfile = Path('/tmp/myfile.txt')
>>>
>>> myfile.touch()
>>>
>>> myfile.write_text('hello\n')
6
>>> myfile.read_text()
'hello\n'
>>>
>>> myfile.unlink()
Join paths:
>>> mydir = Path('/tmp/mydir')
>>> myfile = mydir / 'myfile.txt'
>>>
>>> myfile
PosixPath('/tmp/mydir/myfile.txt')
>>>
>>> myfile.absolute()
PosixPath('/tmp/mydir/myfile.txt')
>>>
>>> myfile.relative_to('/tmp/')
PosixPath('mydir/myfile.txt')
Names:
>>> myfile = Path('/tmp/mydir/myfile.txt')
>>>
>>> myfile.name
'myfile.txt'
>>>
>>> myfile.stem
'myfile'
>>>
>>> myfile.suffix
'.txt'
>>>
>>> myfile.parent
PosixPath('/tmp/mydir')
>>>
>>> myfile.parent.parent
PosixPath('/tmp')
18.1.5. Logging
SetUp:
>>> import logging
Configuration:
>>> logging.basicConfig(
... level='DEBUG',
... filename='/tmp/myfile.log',
... datefmt='%Y-%m-%d, %H:%M:%S',
... format='{asctime}, {levelname}, {message}',
... style='{',
... )
Create logger instance:
>>> log = logging.getLogger('myapp')
Log:
>>> log.debug('Something happened in myapp')
>>> log.info('Something happened in myapp')
>>> log.warning('Something happened in myapp')
>>> log.error('Something happened in myapp')
>>> log.critical('Something happened in myapp')
Usecase:
>>> class User:
... def __init__(self, username, password):
... self.username = username
... self.password = password
... log.debug(f'User {username} created')
...
... def login(self):
... self.authenticated = True
... log.info('User logged-in')
...
... def logout(self):
... self.authenticated = False
... log.info('User logged-out')
18.1.6. JSON
SetUp:
>>> import json
To JSON:
>>> data = {'username': 'alice', 'password': 'secret'}
>>>
>>> json.dumps(data)
'{"username": "alice", "password": "secret"}'
From JSON:
>>> data = '{"username": "alice", "password": "secret"}'
>>>
>>> json.loads(data)
{'username': 'alice', 'password': 'secret'}
18.1.7. CSV
SetUp:
>>> import csv
Dump list[tuple] to CSV:
>>> DATA = [
... ('firstname', 'lastname', 'age'),
... ('Alice', 'Apricot', 30),
... ('Bob', 'Banana', 31),
... ('Carol', 'Corn', 32),
... ('Dave', 'Durian', 33),
... ('Eve', 'Elderberry', 34),
... ('Mallory', 'Melon', 15),
... ]
>>>
>>> with open('/tmp/myfile.csv', mode='wt') as file:
... writer = csv.writer(file, delimiter=',', quotechar='"', quoting=csv.QUOTE_ALL, lineterminator='\n')
... writer.writerows(DATA)
>>>
>>> print(Path('/tmp/myfile.csv').read_text())
"firstname","lastname","age"
"Alice","Apricot","30"
"Bob","Banana","31"
"Carol","Corn","32"
"Dave","Durian","33"
"Eve","Elderberry","34"
"Mallory","Melon","15"
Dump list[dict] to CSV:
>>> DATA = [
... {'firstname': 'Alice', 'lastname': 'Apricot', 'age': 30},
... {'firstname': 'Bob', 'lastname': 'Banana', 'age': 31},
... {'firstname': 'Carol', 'lastname': 'Corn', 'age': 32},
... {'firstname': 'Dave', 'lastname': 'Durian', 'age': 33},
... {'firstname': 'Eve', 'lastname': 'Elderberry', 'age': 34},
... {'firstname': 'Mallory', 'lastname': 'Melon', 'age': 15},
... ]
>>>
>>> with open('/tmp/myfile.csv', mode='wt') as file:
... writer = csv.DictWriter(file, fieldnames=['firstname', 'lastname', 'age'], delimiter=',', quotechar='"', quoting=csv.QUOTE_ALL, lineterminator='\n')
... writer.writeheader()
... writer.writerows(DATA)
29
>>>
>>> print(Path('/tmp/myfile.csv').read_text())
"firstname","lastname","age"
"Alice","Apricot","30"
"Bob","Banana","31"
"Carol","Corn","32"
"Dave","Durian","33"
"Eve","Elderberry","34"
"Mallory","Melon","15"
18.1.8. Itertools
SetUp:
>>> from itertools import permutations, product
Generate test data for music or video player:
>>> actions = ['stop', 'start', 'next']
>>> result = permutations(actions)
>>>
>>> pprint(list(result))
[('stop', 'start', 'next'),
('stop', 'next', 'start'),
('start', 'stop', 'next'),
('start', 'next', 'stop'),
('next', 'stop', 'start'),
('next', 'start', 'stop')]
Generate test cases for file parsing:
>>> files = ['myfile.json', 'myfile.csv']
>>> encoding = ['utf-8', 'cp1250']
>>> modes = ['r', 'w', 'a']
>>> result = product(files, encoding, modes)
>>>
>>> pprint(list(result))
[('myfile.json', 'utf-8', 'r'),
('myfile.json', 'utf-8', 'w'),
('myfile.json', 'utf-8', 'a'),
('myfile.json', 'cp1250', 'r'),
('myfile.json', 'cp1250', 'w'),
('myfile.json', 'cp1250', 'a'),
('myfile.csv', 'utf-8', 'r'),
('myfile.csv', 'utf-8', 'w'),
('myfile.csv', 'utf-8', 'a'),
('myfile.csv', 'cp1250', 'r'),
('myfile.csv', 'cp1250', 'w'),
('myfile.csv', 'cp1250', 'a')]
18.1.9. RE - Regular Expressions
SetUp:
>>> import re
>>> text = 'Mail from Alice <alice@example.com> date: 2000-01-01, time: 00:00.'
Search date in text:
>>> date = r'\d{4}-\d{2}-\d{2}'
>>> re.findall(date, text)
['2000-01-01']
Search email in text:
>>> email = r'<([a-z]+@example.com)>'
>>> re.findall(email, text)
['alice@example.com']
18.1.10. Dataclasses
Instead:
>>> class User:
... def __init__(self, username, password):
... self.username = username
... self.password = password
...
... def __str__(self):
... return self.__repr__()
...
... def __repr__(self):
... clsname = self.__class__.__name__
... username = self.username
... password = self.password
... return f'{clsname}({username=}, {password=})'
You can:
>>> from dataclasses import dataclass
>>>
>>> @dataclass
... class User:
... username: str
... password: str
18.1.11. Doctest
SetUp:
>>> def add(a, b):
... """
... >>> add(1, 2)
... 3
... >>> add(1.0, 2.0)
... 3.0
... """
... return a + b
Run tests:
>>> import doctest
>>>
>>> doctest.testmod()
TestResults(failed=0, attempted=2)
18.1.12. Unittest
SetUp:
>>> def add(a, b):
... return a + b
Write tests:
>>> from unittest import TestCase
>>>
>>> class TestAdd(TestCase):
... def test_add_int(self):
... result = add(1,2)
... self.assertEqual(result, 3)
...
... def test_add_float(self):
... result = add(1.0,2.0)
... self.assertAlmostEqual(result, 3.0, places=16)
Run tests:
>>> import unittest
>>>
>>> unittest.main()