4       Python工程打包部署

Python程序在提供给用户使用时,要脱离Python开发环境运行,此时,需要对python工程进行打包。

常用的Python打包工具有PyInstaller, py2exe等。

4.1     PyInstaller

  • 特点

一条命令即可完成打包。

以GPL标准许可发布,但可用于闭源商业性质的打包使用。

早先的版本不支持Python 3.x版本,最新的版本已经支持,并且具有跨平台特性,首选打包工具。

  • 安装

pip install pyinstaller

pyinstaller.exe将安装到Python安装目录的Scripts目录下,和pip工具在相同路径。

  • 打包命令简介

基本命令形式:

pyinstaller yourprogram.py

其中yourprogram.py是程序入口源文件。

-p指令

这个指令后面可以增加pyinstaller搜索模块的路径。因为应用打包涉及的模块很多。这里可以自己添加路径。不过经过笔者测试,site-packages目录下都是可以被识别的,不需要再手动添加。

-F指令

注意指令区分大小写。这里是大写。使用-F指令可以把应用打包成一个独立的exe文件,否则是一个带各种dll和依赖文件的文件夹。

-w指令

直接发布的exe应用带命令行控制台窗口,在指令内加入-w命令可以屏蔽。

--icon指令

为打包的exe指定图标。

-v指令

指定版本信息。

以上是最常用的几个可选参数指令,更多详细功能介绍可以参考PyInstaller官网:

http://www.pyinstaller.org/

如果Python项目工程比较复杂,可以编写一个python脚本辅助执行打包命令。

4.2     py2exe

官网地址:

http://www.py2exe.org/

  • 特点

py2exe也是比较常用的打包工具,py2exe 是在 Distutils 的基础上扩展了一个新的 "命令"。

所以使用py2exe进行打包,需要编写一个带有setup指令的脚本。

  • 安装

pip install py2exe

SourceForge网站提供有历史版本的下载:

http://prdownloads.sourceforge.net/py2exe

安装完成后,lib\site-packages\py2exe\samples目录下含有使用py2exe打包的样例。

  • 使用

可以参考官方的使用教程:

http://www.py2exe.org/index.cgi/Tutorial

  • 注意

使用py2exe打包完成后,包含有一个名为library.zip的压缩包,压缩包内包含了所有python源文件编译后的的pyc或者pyo字节码文件。但是pyc和pyo很容易被反编译回Python源码,这一点需要注意。

5       Python常用编码技巧

5.1     Python编程规范

Python官方PEP8标准编程规范:

https://www.python.org/dev/peps/pep-0008/

python集成开发环境当中介绍的PyCharm,在编码过程中自带有官方PEP8标准的编程规范提示,推荐使用。

实际使用时,可以根据公司或者部门的代码特点进行更新或者扩展。

5.2     时间模块

  • 等待一段时间

import time

time.sleep(5)

  • 获得当前时间,时间差

方法1:

import datatimeimport timestart_t = datetime.datetime.now() #get current timetime.sleep(3)end_t = datetime.datetime.now()tdiff = (end_t - start_t).seconds

方法2:

import timet1 = time.localtimetime.sleep(3)t2 = time.localtimetdiff = time.mktime(t2) - time.mktime(t1)if int(my_time_diff) > 30:print “30 seconds time out”

5.3     序列类型

序列类型包括元组,字典和字符串,以下语法这三种类型全部适用。

5.3.1  序列类型的访问

以常量字符串a = “1234567890”,进行举例说明:

  • 索引访问

>>> a[3]'4'
  • 切片访问
>>> a[2:5]'345'>>> a[:5]'12345'>>> a[5:]'67890'>>> a[:]'1234567890'
  • 按步长访问
>>> a[2:9:2]'3579'>>> a[::2]'13579'
  • 倒序访问
>>> a[-2]'9'>>> a[::-1]'0987654321'

5.3.2  序列类型的操作

长度:len()

连接:+

重复:*

判断元素是否在序列中:in

最大值:max()

最小值:min()

比较是否相同:cmp(elem1, elem2)

5.4     多级字典

多级字典不能一次性赋值,比如

              level2_dict[“lvl1”][“lvl2”] = “result”

这样就会报错。只能分两步。

              level2_dict[“lvl1”] = {}level2_dict[“lvl1”][“lvl2”] = “result”

5.5     字符串

字符串的基本方法这里不做过多介绍,主要介绍一些字符串的实际使用技巧。

5.5.1  字符串的打印

Python的打印是不需要加入’\n’就能换行的,这点要注意,和其他的语言不太一样。

5.5.2  格式化字符串

  • 通过%实现

>>> "my name is %s, I'm %d years old."%("mike", 15)"my name is mike, I'm 15 years old."
  • 字符串类format方法

按照参数索引:

>>> "my name is {0}, I'm {1} years old.".format("mike", 15)"my name is mike, I'm 15 years old."

按照参数名称:

>>> "my name is {name}, I'm {age} years old.".format(name="mike", age="15")"my name is mike, I'm 15 years old."

5.5.3  数字和字符串转换

  • 强制类型转换

my_str = str(my_num)my_num = int(my_str)
  • 通过string类方法
>>> import string>>> a="12345">>> string.atoi(a)12345>>> b="123.678">>> string.atof(b)123.678

5.5.4  正则表达式

Python对于字符串的操作十分简单方便,结合内置正则表达式re模块,几乎可以完成所有字符串操作的需求。

  • 查找所有匹配字串

>>> import re>>> tt = "Tina is a good girl, she is cool, clever, and so on...">>> rr = re.compile(r'\w*oo\w*')>>> print(rr.findall(tt))['good', 'cool']
  • 从开始位置匹配
>>> print(re.match('com\w*.', 'comwww.runcomoob').group())comwww.
  • 从任意位置匹配
>>> print(re.search('\dcom', 'www.4comrunoob.5com').group())4com
  • 按组匹配
>>> a = "123abc456">>> print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(0)) # 索引0表示返回匹配的整体123abc456>>> print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(1))123>>> print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(2))abc>>> print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(3))
  • 迭代器匹配
>>> iter = re.finditer(r'\d+', '12 drumm44ers drumming, 11 ... 10 ...')>>> for i in iter:print(i)print(i.group())print(i.span())<_sre.SRE_Match object at 0x02517F38>       # 匹配到的Match对象12                                                                                                                          # 匹配到的子串(0, 2)                                                                                                                       # 匹配到的字串的索引<_sre.SRE_Match object at 0x02526250>44(8, 10)<_sre.SRE_Match object at 0x02517F38>11(24, 26)<_sre.SRE_Match object at 0x02526250>

替换匹配到的字串

>>> text = "Mike is a handsome boy, he is cool, clever, and so on...">>> print(re.sub(r'\s+', '-', text))Mike-is-a-handsome-boy,-he-is-cool,-clever,-and-so-on...

并获得替换的个数:

>>> print(re.sub("g.t", "have", 'I get A,  I got B ,I gut C'))I have A,  I have B ,I have C>>> print(re.subn("g.t", "have", 'I get A,  I got B ,I gut C'))('I have A,  I have B ,I have C', 3)
  • 以正则表达式作为分隔符
>>> print(re.split('\d+', 'one1two2three3four4five5'))['one', 'two', 'three', 'four', 'five', '']

5.6     断言

Python中的assert是判断表达式是否为True的断言关键字,例如判断实例是否属于一个类:

assert isinstance(rsm_info_preview, RsmKeyInfo)

5.7     系统命令

  • 路径的操作

ll_test_path = os.path.join(os.path.dirname(__file__),"win32", "IEDriver.dll")

os.path.dirname(__file__)表示当前file的位置。

  • 退出程序

Import syssys.exit()

注意有的时候在函数和类并不能使整个程序退出,注意尽量在主函数里退出才可以。

  • 调用系统命令

os.system(“xxx”)

阻塞命令,需要等待系统命令调用完成才能返回,成功返回0,失败返回1。

  • 启动一个应用

os.startfile(“xxx”)

非阻塞命令,单纯启动命令,执行后立即返回,与目标应用不存在从属关系。相当于双击操作。

  • 管道调用

os.popen(“xxx”)

执行后,启动一个进程,返回文件描述符对象,利用该对象可以捕获该进程的输出。

  • 命令行

commands模块

纯命令行调用模块,可以获得命令的输出或(且)返回值。

  • 进程高级

subprocess模块

更为高级的进程管理模块,提供比os.popen更加高级的接口,可以实现复杂的多进程管理。

5.8     lambda

在Python中,lambda是匿名函数的关键字。

lambda可以定义一句代码覆盖的方法或者函数。大部分情况下,lambda函数当做参数传递给其他方法或者函数,在方法或者函数内部实现动态调整计算实现的过程。类似模板方法设计模式的思路。

5.8.1  基本语法

>>> add = lambda x, y: x + y>>> add(2,3)

5

如上面例子,lambda表达式中,除了lambda关键字,冒号左边等价于def函数的入参,冒号右边等价于def函数的函数体中的return返回值。

整个lambda表达式可以作为一个函数的引用,赋值给一个变量(即例子中的add)。

5.8.2  常用内建函数

lamda结合内建函数map, reduce, filter可以实现强大的序列类型(元组,列表,字符串)的处理功能。

  • map

内建函数map可以得到入参序列中逐个元素按照lambda函数处理后返回的序列。省去循环代码实现的过程。

              >>> list1 = range(5)>>> print list1[0, 1, 2, 3, 4]>>> map(lambda x: x*2, list1)[0, 2, 4, 6, 8]

如上代码实现了列表中每个元素乘2的效果。

  • reduce

内建函数reduce进行两两元素的迭代计算,每次迭代,将上一次的迭代结果(第一次时为initial的元素,如没有initial则为列表的第一个元素)与下一个元素一同执行一个二元的lambda函数,最终得到一个计算结果。

>>> list1[0, 1, 2, 3, 4]>>> reduce(lambda x, y: x + y, list1)10>>> reduce(lambda x, y: x + y, list1, 2)12

如上代码实现了列表求和的效果。

  • filter

该内建函数的作用相当于一个筛选器。lambda函数是一个布尔函数,filter调用这个布尔函数,将每个列表中的元素依次经过一次筛选,选出使lambda返回值是Ture的元素的序列。

>>> list1[0, 1, 2, 3, 4]>>> filter(lambda x: x % 2 == 1, list1)[1, 3]

如上代码实现了筛选列表中所有奇数的效果。

5.9     字符串也是代码

5.9.1  eval

eval可以执行字符串参数的表达式,并返回表达式执行完成的结果。

>>> eval("((1+2)*3.0/4)**2")5.0625>>> eval("'hello '*2")'hello hello '>>> list1 = eval("[1,0.5,[3,4], 'hello python', {1:'one'}]")>>> list1[1, 0.5, [3, 4], 'hello python', {1: 'one'}]>>> type(list1)<type 'list'>

5.9.2  exec

exec可以执行字符串中的代码。

>>> exec("print 'hello python'")hello python>>> exec("for i in range(3):print i")012

5.9.3  区别和使用

eval需要传入的是一个表达式,执行完成后会返回一个结果;exec则是执行字符串内包含的python代码,并不会返回结果。两者不能混用。

因为eval和exec的存在,大大增加了python代码的灵活性。程序可以在运行时状态动态生成代码去执行,可以留作热更新的接口,免去重新编译和打包的过程。不过也因此,带来编码安全的隐患,恶意的字符串注入,将可以执行任意代码。使用时需谨慎。

5.10   yield

一个带有 yield 的函数就是一个 generator,它和普通函数不同,生成一个 generator 看起来像函数调用,但不会执行任何函数代码,直到对其调用 next()才开始执行。虽然执行流程仍按函数的流程执行,但每执行到一个 yield 语句就会中断,并返回一个迭代值,下次执行时从 yield 的下一个语句继续执行。看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。

如下就生成了一个斐波那契数列的生成器:

>>> def fib(max):a, b = 1, 1while a < max:yield aa, b = b, a+ b>>> fib_gen = fib(15)>>> fib_gen.next()1>>> fib_gen.next()1>>> fib_gen.next()2>>> fib_gen.next()3>>> fib_gen.next()5>>> fib_gen.next()8>>> fib_gen.next()13>>> fib_gen.next()Traceback (most recent call last):File "<pyshell#100>", line 1, in <module>fib_gen.next()StopIteration

可以看到,在使用next()的时候要注意生成器的生成边界。

在for循环当中,会自动调用 next(),并在触发StopIteration异常时自动捕获终止:

>>> for n in fib(15): print n11235813

yield的实时性更高,只有在调用的时候才真正执行,可以控制对于系统资源的消耗。

5.11   dir, setattr, getattr,hasattr

这四个函数是Python的内建函数,结合起来使用可以获取对象的属性信息,动态调整对象的属性和值。

>>> class BaseClass(object):'''classdocs'''def __init__(self, first, second, third=3, forth=4):self.first = firstself.second = secondself._third = thirdself.__forth = forthprint "in init"def __del__(self):print "in del"def first_func(self):print "in first func"def _second_func(self, para1):passdef __third_func(self, para1, para2=0):pass>>> A = BaseClass(1, 2)>>> dir(A)['_BaseClass__forth', '_BaseClass__third_func', '__class__', '__del__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_second_func', '_third', 'first', 'first_func', 'second']>>> getattr(A, "first")1>>> getattr(A, "first_func")()in first func>>> hasattr(A, "five")False>>> setattr(A, "five", 5)>>> A.five5>>> hasattr(A, "five")True

这一组内建函数为Python的面向对象特性进行了灵活性扩展,不过完全越过了对于类中成员的保护,在使用时需要注意成员访问的权限问题。

作者|lurayvis 撰写初稿,fhk精美更新

Python精确指南-第四章部署和技巧.pdf

来源:华为云社区  作者:lurayvis

Python精确指南——第四章-部署和技巧相关推荐

  1. Python精确指南——第三章 Selenium和爬虫

    3       Selenium 3.1     介绍 网络爬虫在互联网领域有着广泛的应用. Selenium是一个页面自动化控制框架.能够模拟实际操作,自动化获取网站提供的页面资源信息. Selen ...

  2. Python精确指南——第二章 界面开发

    2 Python GUI 借助Python语言的优势,使用Python的界面库开发界面程序,开发周期更短.但因为Python的界面开发库底层实现一般不是Python,只是为Python封装的接口,所以 ...

  3. Python精确指南-第一章环境

    1       Python开发环境搭建 1.1     Python版本介绍 Python目前官方运营维护的版本分为2.x版本和3.x版本. 2.x版本相对来说,稳定性更高,兼容的主流第三方扩展库更 ...

  4. Java7并发编程指南——第四章:线程执行器

    Java7并发编程指南--第四章:线程执行器 @(并发和IO流) Java7并发编程指南第四章线程执行器 思维导图 项目代码 思维导图 项目代码 GitHub:Java7ConcurrencyCook ...

  5. 数据结构与算法python语言实现-第四章答案

    数据结构与算法python语言实现-第四章答案 4.1 def findmax(S, index=0):if index == len(S) - 1:return S[index]max=findma ...

  6. 零基础学Python课后实战第四章

    零基础学Python课后实战第四章 实战一:输出王者荣耀的游戏角色 实战二:模拟火车订票系统 实战三:电视剧的收视率排行榜 tips 实战一:输出王者荣耀的游戏角色 列表的创建.遍历列表 代码 pri ...

  7. ZeroMQ 中文指南 第四章 可靠的请求-应答模式【转载】

    此文章转载自GitHub : https://github.com/anjuke/zguide-cn 作者信息如下. ZMQ 指南 作者: Pieter Hintjens ph@imatix.com, ...

  8. 我要翻译《Think Python》- 006 第四章 学习案例:接口设计

    本文翻自:Allen B. Downey --<Think Python> 原文链接:http://www.greenteapress.com/thinkpython/html/think ...

  9. Kali Linux 无线渗透测试入门指南 第四章 WLAN 加密缺陷

    第四章 WLAN 加密缺陷 作者:Vivek Ramachandran, Cameron Buchanan 译者:飞龙 协议:CC BY-NC-SA 4.0 简介 任何人对于内存的需求,都不会超过64 ...

最新文章

  1. 二十年后我发明了保姆机器人作文_我想发明保姆机器人作文700字
  2. 分享:游戏新手引导程序框架设计3要点
  3. 创新工场CE0李开复:互联网创业黄金时代来临
  4. 利用bladex+avue实现下拉数据源展示
  5. 关于android资源文件名称的规范
  6. android optionmenu 动态显示,android – 如何在onCreateOptionsMenu中动态更改菜单
  7. access mysql odbc驱动程序_access odbc驱动程序
  8. Maple 全面基础
  9. PP点点通畸形文件溢出漏洞0Day
  10. Opencv获取DroidCamx视频流并改变分辨率
  11. sublime php code sniffer,Sublime插件CodeSniffer配置
  12. 校园学生管理系统设想
  13. ckeditor java 使用教程_Java上CKEditor集成指南
  14. 正方形数目 cmp 栈
  15. 编程语言python这个词怎么翻译_五大理由从 Python 转到 Go 语言【已翻译100%】...
  16. C# 处理PPT水印(二)——去除水印效果(文本水印、图片水印)
  17. 网站favicon图标(网站标志,显示在浏览器地址栏或标签上)
  18. NMAP常见命令总结
  19. OCam 录制,可变帧率、码率及恒定帧率、码率详解
  20. arm架构和x86架构有什么区别

热门文章

  1. mysql 多个库一起导出_MYSQL 导出多个库
  2. 渭南师范计算机科学与技术,渭南师范学院计算机科学与技术专业2016年在陕西理科高考录取最低分数线...
  3. python调用java文件_Python程序中调用Java代码的实践
  4. vscode + angular
  5. python 机器学习第一章
  6. 读取数据库并写入excel表中 发送邮件
  7. php 请求远程链接
  8. 一、JSP的基本原理
  9. 倍福TwinCAT(贝福Beckhoff)常见问题(FAQ)-如何修改某个轴的数值单位
  10. http参数修改以及拦截