Poznámky z PyCON UK 2014

Měl jsem možnost se podívat na PyCON UK a nelituji. Odnesl jsem si spoustu nových znalostí, tipů, na co se podívat či co aplikovat v praxi. Něco málo předám dál.
Text původně vyšel na autorově blogu.
Logování
Můžete se snažit jak chcete, ale uživatelé vždycky najdou chyby ve vašich aplikacích. Kvůli tomu je potřeba si zajistit dobré logování a o tom byla jedna z prvních přednášek. Tipy jsou poměrně jasné, ale je dobré si je připomenout, stejně jako tak prozkoumat, zda neexistují nějaké nové pomůcky, které se mohou hodit.
Základ je logovat tak, aby šlo chybu jednoduše znovu vyvolat. Ještě lepší by byl formát, abych to mohl jednoduše hodit do unit testů. Což je sice hezká idea, ale přednášející ji dál nerozváděl a nedovedu si představit, jak něco takového zautomatizovat. Ale rozhodně stojí za zamyšlení. U webovek by šlo třeba generovat aspoň základ Seleniového testu…
Během přednášky zaznělo několik toolů na správu reportovaných chyb. Z nich mě zaujal například Sentry, který zvládne víc, než jen sbírat chyby, ale také umí vyhledávat duplicity. Mám chuť už dlouho udělat u naší aplikace automatické nahrávání bugů do systému, od čehož mě stále odrazují duplicity. Přednáška mi sice nedala odkaz na tool, který by se mi přesně hodil, ale minimálně mne nakopla k tomu se k tomuto problému vrátit a konečně vyřešit.
Refaktorování
Další obsahově zajímavá přednáška byla o Rope. Pythoní balík umožňující refaktoring. Občas se hodí udělat přejmenování některé proměnné, která je prolezlá všude možně. To se pak do práce moc nechce. Proto mne seznámení s Rope potěšilo. Škoda jen, že zatím není tolik propojení s editory (pro vim či emacs plugin samozřejmě existuje). Proto vznikl projekt Traad, který je nadstavba nad Rope komunikující v JSON, s čímž dnes komunikuje snad každý. Jsem zvědav, zda to podpoří vytvoření pluginů pro další editory.
Jak jsem však zmínil, jedná se o pythoní balík s API v Pythonu. Takže to lze pouštět hacker stylem. V následujícím příkladu přejmenovávám třídu nazvanou ClassName
v modulu module.py
na NewClassName
. Hezké na Rope je, že, co jsem zkoušel, zvládne projít codebase a nahradit opravdu všude, kde se používá. Což například mé oblíbené Komodo IDE nezvládne.
project = rope.base.project.Project('.')
module = project.get_file('module.py')
offset = module.read().index('ClassName')
changes = rope.refactor.rename.Rename(project, module, offset).get_changes('NewClassName')
project.do(changes)
Hezké také na Rope je, že při volání project.history.undo()
vrátí všechny změny z několika souborů najednou. Více informací na GitHubu projektu.
Prezentace z přednášky.
Testování
Většinou, když se jde v Pythonu testovat, sáhne se po knihovně unittest
. Nejsem si jist, zda jsem opravdu neslyšel o knihovně pytest
, nebo zda jsem zaslechl, ale vůbec jsem se nepodíval a pustil to z hlavy. Každopádně mne její představení mile překvapilo.
Klasický unittest
řeší testování a nějaký ten setUp
pro přípravu testovacího prostředí. U větších projektů to nemusí stačit a je potřeba si fixtures pořešit nějak jinak. V práci jsme si udělali docela dobrý jednoduchý systém. Píšu docela, protože stále to není ono. Na pytest
u se mi líbí, že právě tyto problémy má vyřešené, resp. obsahuje hezkou práci s fixtures, a to hezky.
Napíšete jednoduše test, do parametru přidáte fixture(s), napíšete tyto fixtury, které označíte dekorátorem, a pustíte. Hotovo. Může to vypadat nějak takto:
@pytest.fixture(scope='module', params=['mysql', 'postgresql'])
def db_conn(request):
return create_db_conn(request.params)
@pytest.yield_fixture
def db_table(db_conn):
db_table = db_conn.make_db_table()
yield db_table
db_table.drop
def test_one(db_table):
...
Na této ukázce je hned několik věcí, které se mi líbí:
- Každý test má jen takové fixtury, které potřebuje. U
unittest
u je jedensetUp
pro třídu. Pokud tam budete mít jeden test, který patří do této sady, ale nepotřebuje všechny fixtury, vytváří se některé zbytečně (drahocené milisekundy). - Fixtury mohou na sebe záviset, stejně jako závisí test na fixtuře. Není potřeba si dělat vlastní systém, kdy při použití tabulky musím také vytvářet konexi do databáze.
- U fixtury mohu říct její platnost. To je v ukázce u
db_conn
určeno pomocí parametruscope
, čímž říkáme, že chceme konexi sdílet pro modul nazvanýmodule
. Konkrétní ukázka je obdobasetUpModule
, ale nemusím v každém modulu tuto funkci definovat – napíšu jednou bokem a použiji, kde potřebuji, jako závislost. - Pro více parametrů se volá test vícekrát. Například v ukázce výše máme jeden test. Zavolá se však dvakrát. Jednou pro databázi MySQL a jednou pro PostgreSQL. Samozřejmě, pokud použiji u jednoho testu více fixtur a každá bude mít různé parametry, vyzkouší se daný test se všemi možnostmi.
- Vytváření a rušení fixtur je hezky v jedné metodě vedle sebe.
Na jednoduché aplikace to nemusí mít moc velký wow efekt, ale co mi řeklo, že to rozhodně musím vyzkoušet na jakémkoliv dalším projektu, je zobrazení selhání:
def test_add():
a = 1
b = 2
expected = 4
> assert add(a, b) + add(b, b) == expected
E assert (3 + 4) == 4
E + where 3 = add(1, 2)
E + and 4 = add(2, 2)
test_pytest_examples.py:12: AssertionError
Normálně byste jen viděli, že 7 != 4. pytest
však udělá menší analýzu kódu a rozpadne jednotlivé volání v příkazu. Tak můžete rychle najít, kde je problém. Šikovné. Mimochodem nad testem je také vidět, jaké fixtures byly do testu posílány.
Jinak vidíte správně – využívá se klasický assert
. Žádné volání různých metod. Zde vidím jednu nevýhodu, a to, že tímto způsobem není možné nahradit metodu assertAlmostEqual
, musí se ručně psát něco jako assert abs(foo) < 0.0001
. Když si ale vzpomenu, kolikrát jsem tuto metodu využil, chybět mi nebude.
Prezentace srovnání unittestu a pytestu. Dokumentace k pytestu.
Práce s daty
V poslední době mne zajímá téma machine learning a tak bylo jasné, že na workshop Practical introduction to machine learning via Kaggle problems musím zajít. Moc ohledně samotného machine learningu jsme se nedozvěděli. Celé nás to spíš provázelo problémem „máme nějaká neúplná data a potřebujeme je nějak transformovat do podoby, abychom mohli předvídat“. I to však přineslo své ovoce – seznámení s knihovnou pandas
.
V práci děláme na obchodní aplikaci se spoustou statistik a vždy s těmi daty operujeme docela neohrabaně. Resp. nikdy mi nepřišlo, že ten styl je až tak neohrabaný, dokud jsem se neseznámil s pandou. Tato knihovna umí doslova psí kusy. Přesvědčte se sami:
In [55]: df['one'] Out[55]: a 1 b 2 c 3 d NaN Name: one, dtype: float64 In [56]: df['three'] = df['one'] * df['two'] In [57]: df['flag'] = df['one'] > 2 In [58]: df Out[58]: one two three flag a 1 1 1 False b 2 2 4 False c 3 3 9 True d NaN 4 NaN False
Viz dokumentace.
Může se to zdát tak trochu jako ne-pythonovský přístup, ale líbí se mi. Je dost praktický. Složitá transformace dat lze provést jednoduše, čitelně. Je to další dokumentace, kterou si budu muset projít, abych měl přehled, kdy si budu moct jak zjednodušit práci. Hlavně odstranit zbytečné chyby. Brzy nás čekají velké úpravy statistik, tak se těším na použití. :-)
Dokumentace k pandě.
Requests
Určitě jste už někdy v Pythonu dělali nějaké requesty a určitě jste se trápili s modulem urllib
. Případně jste už sáhli po lepším balíku requests
, ale použili jste pouze requests.get('url').content
. Víte však, co všechno tento balík zvládne a jak je sexy? Pro příště mám jasno, co použiji. Před chvílí jsem si zrovna upravil jedno použití a hned to vypadá lépe.
Závěr
Na konferenci zaznělo samozřejmě více zajímavých přednášek. Pokud prahnete po dalších informacích, mrkněte na program a dohledejte si prezentace k tomu, co vás zajímá. Všechny přednášky v místnosti HP room byly nahrávány, takže se časem na internet dostanou i záznamy. Případně se můžete podívat na videa z jiných PyCON konferencí, která jsem postoval nedávno.
Ahoj,
diky za clanek a inspiraci. Jen bych rad upozornil, ze knihovna pro praci s daty se nejmenuje panda, ale pandas.
Doporucuji se podivat take na DataFrame – obdoba stejnojmenne datove struktury z R. Ma par zajimavych vychytavek (zkuste describe a pivot_table :-) ).
V.
Pandu jsem opravil, díky za upozornění.
Pytest doporučuji, používám ho u nás v práci a nemůžu si ho vynachválit.