Python je momentalne muj nejoblibenejsi jazyk. Je rychly na prototypovani, umoznuje psat kratke skripty, velke GUI aplikace, webove stranky,…
Jednou z jeho nejvetsich (ne)vyhod je, ze jde o interpretovany jazyk. Tudiz je pomalejsi, nez jazyky kompilovane a kazdy muze videt zdrojovy kod.
Problem se nastesti da relativne snadno vyresit kompilaci.
Nebudu to rozebirat nijak do hloubky. Kdo chce podrobnosti, odkazu ho na pouzite zdroje v zaveru a na Google. Jde pouze o ukazani moznosti.
Prvni ukazka. Jednoduchy program na vypis aktualniho casu. Po spusteni jako samostatny program vypise cas a ukonci se. Pri importu jako modul v pythonu nevypise nic, ceka na zavolani funkce cas().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
from datetime import datetime def mojeFunkce(cas): print "Je %s hodin." % cas def cas(): hodiny = datetime.now().strftime('%H:%M:%S') mojeFunkce(hodiny) if __name__ == '__main__': print "_RUN_" cas() else: print "import" |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
martin@martin:~$ cython --embed prvni.py martin@martin:~$ gcc prvni.c -I/usr/include/python2.7 -lpython2.7 -o prvni martin@martin:~$ s -lh celkem 172K -rwxr-xr-x 1 martin martin 48K pro 8 13:03 prvni -rw-r--r-- 1 martin martin 112K pro 8 13:03 prvni.c -rw-r--r-- 1 martin martin 268 pro 8 13:02 prvni.py -rw-r--r-- 1 martin martin 541 pro 8 13:02 prvni.pyc martin@martin:~$ strip prvni martin@martin:~$ ls -lh celkem 164K -rwxr-xr-x 1 martin martin 37K pro 8 13:03 prvni -rw-r--r-- 1 martin martin 112K pro 8 13:03 prvni.c -rw-r--r-- 1 martin martin 268 pro 8 13:02 prvni.py -rw-r--r-- 1 martin martin 541 pro 8 13:02 prvni.pyc martin@martin:~$ ./prvni _RUN_ Je 13:03:19 hodin martin@martin:~$ python Python 2.7.6 (default, Jun 22 2015, 17:58:13) [GCC 4.8.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import prvni >>> prvni.cas() Je 13:03:33 hodin. >>> martin@martin:~$ ldd ./prvni linux-vdso.so.1 => (0x00007fff957fe000) libpython2.7.so.1.0 => /usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0 (0x00007f5f68c47000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5f68882000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f5f68663000) libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f5f6844a000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f5f68246000) libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007f5f68042000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f5f67d3c000) /lib64/ld-linux-x86-64.so.2 (0x00007f5f691db000) martin@martin:~$ |
Prvni prikaz (cython) vegeneruje z pythoniho zdrojoveho kodu C zdrojovy kod. Je tezko clovekem citelny, protoze je generovany. Parametr embed zajisti pridani main() funkce. Cython dokaze generovat C a C++ zdrojaky a pouzivat Python2, nebo Python3.
Pote je mozne vygenerovany C soubor pomoci gcc zkompilovat. Stripnuta binarka ma jenom 37kB.
Pri spusteni jako samotny program (./prvni) vypise _RUN_. Zavislosti (viz vystup ldd) jsou bezne linuxove knihovny plus navic libpython.
Druha ukazka je o trochu slozitejsi. Pomoci skvele knihovny requests stahne JSON z meteostanice a vypise aktualni teplotu.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
import requests import json import time import sys try: debug = sys.argv[1] except IndexError: debug = 0 def stahniData(debug): url = 'http://teplomer.jicin.cz/vystup-json.php' headers = {'user-agent': 'Python_test_app/0.0.1'} r = requests.get(url, headers=headers) odpovedText = r.text if debug: print odpovedText data = json.loads(odpovedText) teplota = str(data['teplota']) cas = str(data['cas']) return teplota, cas while True: print 'Aktualne je {0}C, v {1}.'.format(*stahniData(debug)) time.sleep(5) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
martin@martin:~$ cython --embed druhy.py martin@martin:~$ gcc druhy.c -I/usr/include/python2.7 -lpython2.7 -O3 -o druhy martin@martin:~$ ls -lh celkem 340K -rwxr-xr-x 1 martin martin 45K pro 8 13:12 druhy -rw-r--r-- 1 martin martin 125K pro 8 13:12 druhy.c -rw-r--r-- 1 martin martin 573 pro 8 13:11 druhy.py martin@martin:~$ strip druhy martin@martin:~$ ls -lh celkem 328K -rwxr-xr-x 1 martin martin 34K pro 8 13:13 druhy -rw-r--r-- 1 martin martin 125K pro 8 13:12 druhy.c -rw-r--r-- 1 martin martin 573 pro 8 13:11 druhy.py martin@martin:~$ file druhy druhy: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=4afeb4fa92c52bf9bb549e838525ca3416281bb9, stripped martin@martin:~$ ldd ./druhy linux-vdso.so.1 => (0x00007fff0e72b000) libpython2.7.so.1.0 => /usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0 (0x00007f9a35878000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9a354b3000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f9a35294000) libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f9a3507b000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f9a34e77000) libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007f9a34c73000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f9a3496d000) /lib64/ld-linux-x86-64.so.2 (0x00007f9a35e0c000) martin@martin:~$ ./druhy Aktualne je 7.1C, v 2015-12-08 13:12:35. Aktualne je 7.1C, v 2015-12-08 13:12:35. ... martin@martin:~$ ./druhy 1 { "teplota": 7.1, "vlhkost": null, "cas": "2015-12-08 13:12:35", "umisteni": "<a href="http://www.mapy.cz/s/hgUU">Zizkovo nam. 18</a>" } Aktualne je 7.1C, v 2015-12-08 13:12:35. { "teplota": 7.1, "vlhkost": null, "cas": "2015-12-08 13:12:35", "umisteni": "<a href="http://www.mapy.cz/s/hgUU">Zizkovo nam. 18</a>" } Aktualne je 7.1C, v 2015-12-08 13:12:35. ... martin@martin:~$ |
Mezi hodne zajimave vyhody kompilace Pythonu patri i mozne zrychleni. Python je dynamicky silne typovany jazyk. Neustale zjistovani a kontrola typu zpusobuje znatelne zpomaleni behu programu. Zvlast u nekterych vypoctu je rozdil obrovsky (proto se na vypocty ma pouzivat NumPy). Proto umoznuje Cython nadefinovat promennym datove typy.
Hodne zajimave je toto PDF. Urcite doporucuji precist. Z neho je take nasledujici ukazka:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
def exp(x, terms = 50): sum = 0. power = 1. fact = 1. for i in range(terms): sum += power/fact power *= x fact *= i+1 return sum # doba behu pro 50 000 - 1,05s def exp(double x, int terms = 50): cdef double sum cdef double power cdef double fact cdef int i sum = 0. power = 1. fact = 1. for i in range(terms): sum += power/fact power *= x fact *= i+1 return sum # doba behu pro 50 000 - 0,042s # rozdil - 25x |
Aneb jak se pise na oficialnim webu Cythonu: „Cython is Python with C data types“ (Cython je Python s C datovymi typy).
Pouzite zdroje: