使用 Cython 加密 Python 项目

最近公司需要将 python 代码部署到端上查了各种加密方法说到底 python 其实是不建议加密部署的,像什么生成.pyc其实都是很容易反编译直接运行的,因为它是解释型语言。不像 C 或者 java 可以编译后生成机器码直接部署。还有看到把项目打包成.exe文件,在 windows 上运行,由于我们使用 Linux 平台没有尝试,最后选择了使用Cython这个库来加密(编译成二进制)。 Cython其实就是把py 代码编译成 C或者 C++代码来执行,在Linux 上会生成.so二进制文件,Windows下为.pyd,所以还有一个作用是加速代码的执行效率。但还有一些限制如项目中不能删除__init__.py否者包导入会失败。详细可参考官方文档,Cython 还在持续开发中支持 Python3,下面也用Python3演示。 先来做一些准备工作定义编译后的文件夹build和一些部署不需要的文件和文件夹,将待编译的.py文件加入ext_modules列表 cur_dir = os.path.abspath(os.path.dirname(__file__)) setup_file = os.path.split(__file__)[1] build_dir = os.path.join(cur_dir, 'build') build_tmp_dir = os.path.join(build_dir, "temp") # define exclude dirs, these dirs will be deleted exclude_dirs = ['.git', '__pycache__', 'test', 'logs', 'venv', 'tests'] # defile exclude files, these files will be deleted exclude_files = ['*.md', '.gitignore', '.python-version', 'requirements.txt', '*.pyc', '*.c'] # these `....

November 3, 2018 · 2 min · 307 words · Fython

collections模块中的namedtuple和defaultdict

collections模块中的namedtuple和defaultdict collections模块是Python中对内置类型(dict, list, tuple)的拓展。就是说它们本身具有普通内置类型的所有特性,并添加了新的功能。 namedtuple() namedtuple(typename, field_names)是tuple的子类,定义的元组可以通过属性访问,也易于理解,self-document。field_names可以是列表或者是通过空格或者逗号分隔的字符串。 >>> from collections import namedtuple >>> Point = namedtuple('point', 'x, y') >>> p = Point(3, y=4) >>> p point(x=3, y=4) >>> p[0] 3 >>> p.x 3 >>> x, y = p >>> print(x, y) 3 4 namedtuple有几个比较有用的方法和属性 SomeNamedTuple._make(iterable)类方法,从可迭代对象中取值,长度必须和传入的field_names一致,返回一个新的对象 somenamedtuple._asdict()方法返回一个有序字典(OrderedDict) somenamedtuple._replace(**kwargs)方法替换值,返回一个新的对象,原来的不变 somenamedtuple._fields属性返回键名(field name),可用于创建新的named tuple 再来看两个官方文档上的例子读取csv文件或者从sqlite读取 EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade') import csv for emp in map(EmployeeRecord._make, csv.reader(open("employees.csv", "rb"))): print(emp.name, emp.title) import sqlite3 conn = sqlite3....

February 9, 2018 · 2 min · 244 words · Fython

Python中的特殊方法

Python 中的特殊方法 python 在定义 class 时有很多特殊方法可以定义,它们一般都是以双下划线开头和结尾如__init__、__call__、__lt__、__iter__、__setattr__、__setitem__等,下面将对这些常用方法作一些总结。 class 基本方法 __new__(cls[, ...]) 我们都知道__init__会在类初始化的时候被调用其实它不是第一个被调用的,第一个是__new__会在对象创建的时候被调用,这时还没有实例化所以它的第一个参数是cls。 __init__(self[, ...]) 最常用的类方法不用过多介绍,对象初始化时自动调用,也就是在__new__之后才会调用。第一个参数是self实例本身。有一点要注意的是它不能返回(return)值,不然会报TypeError记住它是用来初始化对象的。 class A: def __new__(cls): print('__new__ called') return super(A, cls).__new__(cls) def __init__(self): print('__init__ called') a = A() 返回如下,注意这是 Python3 的写法默认A继承自object,如果使用 Python2 的需要指定A继承自object基类,使用新类。不然__new__是不会被调用的。 __new__ called __init__ called 需要注意的是上面我们定义了__new__接收类对象(cls),必须返回return super(A, cls).__new__(cls)这个类实例也就是下面方法的self,因为__new__会被首先调用返回实例对象以供下面的方法如__init__这些使用。如果去掉这一句其他方法会返回None。默认未定义__new__方法时,默认返回父类实例super().__new__(cls, *args, **kwargs) __str__(self) 调用print(obj)或str(obj)时返回的字符串是对人类友好的(human readable string)。 __repr__(self) 调用repr(obj)或obj返回的字符串,比较偏向机器。 __format__(self, format_spec) 调用f string或format时调用,format(value, format_spec)相当于value.__format__(format_spec) class Animal: def __init__(self, name): self.name = name def __format__(self, format_spec): if format_spec == 'view': return f"this is {self....

January 28, 2018 · 3 min · 588 words · Fython

Python中@propery 使用

Python中@propery 装饰器的使用 python是面向对象的语言,当我们想在类中封装一个变量,并提供设置和获取值的时候,往往会使用如下方法。 class Student: def __init__(self, score): self.__score = score def get_score(self): return self.__score def set_score(self, score): self.__score = score 然后如下输出 >>> s = Student(99) >>> s.get_score() 99 >>> s.set_score(100) >>> s.get_score() 100 这是最简单的封装,但有没有像s.score这样属性直接调用s.score = 100直接赋值的呢,有!而且很简单。 class Student: def __init__(self, score): self.score = score 没错就是__init__方法直接设置。 >>> s = Student(99) >>> s.score 99 >>> s.score = 100 >>> s.score 100 以上的方法没有封装,而且如果我想要判断score的值范围(0~100)也无法做到,使用第一种set_score倒是可以做到。 class Student: def __init__(self, score): self.set_score(score) def get_score(self): return self....

October 8, 2017 · 1 min · 204 words · Fython

Python3 协程(Coroutine) 与 asyncio

Python3 Coroutine(协程) 与 asyncio 协程,又称微线程,纤程,英文名 Coroutine。协程的作用,是在执行函数 A 时,可以随时中断,去执行函数 B,然后中断继续执行函数 A(可以自由切换)。但这一过程并不是函数调用(没有调用语句),这一整个过程看似像多线程,然而协程只有一个线程执行。 优势 执行效率极高,因为子程序切换(函数)不是线程切换,由程序自身控制,没有切换线程的开销。所以与多线程相比,线程的数量越多,协程性能的优势越明显。 不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在控制共享资源时也不需要加锁,因此执行效率高很多。 说明:协程可以处理 IO 密集型程序的效率问题,但是处理 CPU 密集型不是它的长处,如要充分发挥 CPU 利用率可以结合多进程加协程。 有一篇David Beazley的课程A Curious Course on Coroutines and Concurrency详细讲解了协程和并发的用法,强烈推荐。本篇文章多处参考与此。 0x01. Generator 与 Coroutine 的区别 一开始我总是傻傻分不清Generator和Coroutine的区别感觉这两个东西差不多不一样吗,最近查了点资料并学习了下。在此做记录,我们先来看Generator。 def countdown(n): while n > 0: yield n n -= 1 c = countdown(5) print(c) for i in c: print(i) 返回一个generator object并且可以迭代,详细参考上一篇文章 <generator object countdown at 0x7f82a41739e8> 5 4 3 2 1 [Finished in 0.0s] 如下是Corountine...

May 18, 2017 · 4 min · 674 words · Fython