python + c = cython

Categorii: Programare, Windows, Unix

28-Feb-2017 17:15 - 684 vizionari

Cython este o solutie de compilare si de optimizare a programelor scrise in Python suficient de eleganta si de matura, care poate fi automatizata.

Daca o solutie nu poate fi automatizata, nu este buna, pentru ca cine nu gandeste, munceste.

Cython este un compilator static, care translateaza codul Python in cod c.

Cython este diferit de cpython. Cpython reprezinta suita de programe (module) scrise in c pentru python, iar Cython este utilitarul de conversie .py –> .c

Conversia in c facuta de Cython nu aduce prea mare spor de viteza, o executie de 3-4 ori mai rapida a rezultat din testele mele, dar cel mai important aspect la programul convertit in c si compilat este posibilitatea mai ridicata de protectie a codului scris in Python. Programele scrise in Python si compilate in format .pyc sau .pyo sunt foarte usor de decompilat, adica sursa originala este foarte usor de aflat, dar un program scris in c, compilat si apoi decompilat este ceva mai greu, dar nu imposibil, de descifrat.

Problema cea mai mare a limbajului Python nu este viteza, avem calculatoare suficient de performante acum, este protectia intelectuala a codului sursa. Fisierele .pyc si .pyo sunt bytecode, adica o translatie a codului Python in limbajul intern al interpretorului Python, un fel de limbaj de asamblare interpretat. Dar cand codul este compilat din c in format executabil, decompilarea este ceva mai dificila si descurajeaza orice hacker incepator.

Multa vreme mi-am pus problema cum sa protejez sursa al unui program Python si exista multe discutii pe aceasta tema pe Internet si sunt oferite multe solutii, dar solutia Cython nu am gasit-o niciodata suficient de bine explicata si de automatizata.

In continuare ofer solutia Cython completa si testata pentru toti programatorii Python.

In primul rand avem nevoie de un compilator c si pentru Linux totul se intampla magic prin comanda:


sudo apt-get install build-essential

Dar pentru Windows este nevoie de ceva mai multe comenzi. Dupa ce se instaleaza Python 2.7 (inca nu ma intereseaza Python 3.x), se instaleaza mingw special customizat si integrat in python cu pip:


python -m pip install -i https://pypi.anaconda.org/carlkl/simple mingwpy

Apoi trebuie configurat Python 2.7 sa compileze orice modul, program sau extensie cu mingw32. In folderul C:\Python27\Lib\distutils trebuie sa existe fisierul distutils.cfg si sa contina:


[build]
compiler=mingw32
;compiler=msvc

[build_ext]
compiler=mingw32
;compiler=msvc

Cred ca aceeasi procedura merge si pentru Python pe 64 de biti combinat cu mingw64.

Cython se instaleaza in Windows sau Linux cu:

 pip install cython 

Modulul de test, fisierul test1.py, scris in Python:



import time

def f1():
    '''
        Functia 1 din test1
    '''
    print "func 1"

def f2():
    '''
        Functia 2 din test1
    '''
    print "func 2"
    print 1/0

def benchmark(s):
  while True:
    a=100
    t1=time.time()
    for j in range(3000):
     for i in range(3000):
       a=a*5.22222222221
       a=a/5.22222222222
    t2=time.time()
    #print '%s : a=%.3f time=%.4f sec' % (s,a,t2-t1)
    print '{} : a={:.3f} time={:.4f} sec'.format(s,a,t2-t1)



if __name__ == "__main__":
    print 'main modul test1'
    benchmark('Main')




Un program utilitar, fisierul mk_ext_module.py, scris in tot Python si care compileaza automat fisierul .c generat de Cython:



import os
from distutils.core import setup, Extension

modulename = os.getenv('MODULENAME',None)

module1 = Extension(modulename,
                    sources = [modulename+'.c'],
                    #cred ca -Os = optimize pt code size, genereaza un cod mai complicat bun pt protectia modulului
                    extra_compile_args=['-Os','-g0','-Wall'],
                    )

setup (name = modulename,
       version = '1.0',
       description = 'Modulul {}.py convertit in {}.c si compilat.'.format(modulename,modulename),
       ext_modules = [module1])


Utilitarul mk_ext_module.py citeste variabila de sistem, MODULENAME, ca sa afle numele programului de compilat.

Un fisier de comenzi windows (.bat sau .cmd) pentru automatizarea compilarii modulului Python:


@echo off
SET MODULENAME=test1
cython %MODULENAME%.py -D --embed -o %MODULENAME%.c
python mk_ext_module.py build
pause

Dupa ce se genereaza fisierul .c (cython test1.py -D --embed -o test1.c), acesta este compilat in format .pyd sau .so (python mk_ext_module.py build)

Testarea modulului se face mai intai necompilat:


python test1.py

Apoi testul modulului compilat:


rem cd in folderul unde este fisierul compilat - test1.pyd
cd build\lib.win32-2.7
python -c "import test1; print dir(test1); test1.f1()"
rem test benchmark
python -c "import test1; test1.benchmark('Compilat:')"

Anumite secvente de cod Python, care necesita o viteza mai mare de executie, sau partea de cod care verifica daca licenta programului este valida: cheia folosita la instalarea aplicatiei si decriptata cu parola interna si greu de aflat, formata din caractere netiparibile, ofera durata de viata a programului, adica daca programul expira si cand, si numarul maxim de utilizatori conectati simultan, plus alte limitari specifice licentei instalate, …

Astfel informatii importante despre functionarea aplicatiei se pot ascunde intr-un modul scris sau convertit in .c combinat (pentru cresterea complexitatii modulului) cu alte functii utile in functionarea programului in speranta ca Hackerul Standard sau Average Joe nu le poate accesa.



Ultimele pagini: RSS

Alte adrese de Internet

Categorii

Istoric



Contorizari incepand cu 9 iunie 2014:
Flag Counter

Atentie: Continutul acestui server reprezinta ideile mele si acestea pot fi gresite.