bumpversion的简单学习

Python Python Module bumpversion 的简单学习 如果只是闭门造车,写点小脚本的话可以不用在意版本的问题。 但是一旦脚本或者项目需要被他人使用,如果没有版本信息,又出现了 bug,那么你很难定位他使用的是什么版本,这个 bug 到底有没有修复,有了版本信息你可以很确定一些 feather 或者 bug 是否实现。 最简单的版本信息制作,在项目下新建一个 VERSION 文件,在该文件中记录版本号,做了些代码修改就手动修改 VERSION。 但是这样会带来更多问题,你只能在修改过 VERSION 后做个 git commit 才能够更好地跟踪;多个文件会提到版本信息该怎么处理;大版本和 patch 版本如何区分? bumpversion 横空出世,给上述的问题给了些答案。Bumpversion 是一个简化工程版本号修改的工具,可以通过 pip 安装。使用它可以一键将当前工程的文件中的旧版本号替换成新版本号还可以顺便 Commit 和 打上 Tag(如有需要)。 语法 bumpversion [options] part [file] 这里面 part 是关键,它可以简化很多事。 使用 先看一个简单的例子: 工程里有 main.py 和 Makefile 两个文件。 main.py 打印当前的版本号: version = '0.0.1' if __name__ == '__main__': print(version) Makefile 将 py 文件压缩起来: VERSION = 0.0.1 .PHONY: build build: tar zcvf tellversion-v$(VERSION).tar.gz main.py 要使用 Bumpversion 需要在目录里添加 .bumpversion.cfg 文件: ...

marshmallow 库的简单学习

[Python [[Python Module]] marshmallow 库的简单学习 marshmallow 是一个简单序列化/反序列化模块。 它可以很轻松的做到 object-->dict objects-->list 等序列化操作,同时经过添加简单的函数做到 dict-->object list-->objects 等反序列化操作。 同时,它对于数据的校检非常友好,有多种校检方式,同时相对于 Schema 库,它可以更有针对性的校检数据,序列化数据等(例如只取某些数据,只校检某些数据等)。 一、简单说明 marshmallow 库非常易于使用,下面将以实际的代码演示如何使用这个库。 先明确下使用流程。 创建类–>创建 Schema 类–>(创建 ValidSchema 类) 序列化<—>反序列化 二、创建Schema类 创建基础的类 # -*- coding:utf-8 -*- from datetime import date from marshmallow import Schema, fields, pprint, post_load from marshmallow import ValidationError, validate, validates class Artist(object): """基础艺术家类""" def __init__(self, name): self.name = name class Album(object): """基础专辑类""" def __init__(self, title, release_date, artist): self.title = title self.release_date = release_date self.artist = artist 根据自己的类创建对应的 Schema 类,继承自 marshmallow 的 Schema 类。 ...

paramiko 库的简单学习

[[Python]] [[Python Module]] paramiko 库的简单学习 paramiko,一个听起来不像英语的库,在诸多英文名的库中独立旗帜(官方解释为:“Paramiko” is a combination of the Esperanto words for “paranoid” and “friend”)。 它的主要功能就是实现对 ssh 协议的封装,能够在一个更高层面上,轻松地使用 ssh 以及 sftp 等功能。 一、安装 pip install paramiko 二、ssh 连接对象 1.使用密码连接 import paramiko # 这行代码可以生成连接日志,大部分情况下不需要 # paramiko.util.log_to_file('/tmp/sshout') ssh = paramiko.SSHClient() #这行代码的作用是允许连接不在know_hosts文件中的主机。 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect("IP", port, "username", "password") 2.使用秘钥连接 import paramiko ssh = paramiko.SSHClient() ssh.connect('10.120.48.109', port, '用户名', key_filename='私钥') 三、ssh 执行指令 成功连接主机后,可以使用 ssh.exec_command(cmd) 的方法执行指令。 但默认返回三个 paramiko.channelfile 对象,我们可以用以下的方法读取数据或者写入确认等。 stdin, stdout, stderr = ssh.exec_command(cmd) # 如果成功,stdout会拿到输出的结果 for line in stdout.readlines(): print(line) # 执行过程中,可以使用以下方法进行确认,但此时的确认是对指令操作过程中的指令,例如“确认删除”等 stdin.write('Y') # 执行过程中若出现错误信息,报错信息会保存在stderr中 四、sftp 对象 paramiko 的 sftp 对象有多种生成方式。 倘若已有 ssh 对象,则: ...

pipenv+virtualenv配置全新的python环境

[[Python]] [[Linux]] 提示信息说三遍,本文最终的结果并不如人意,只是一些探索的过程记录。问题在于:当使用paramiko库时会提示openssh服务,而如果继续封装就有点违背当初的想法,应该有更优秀的解决方案。 提示信息说三遍,本文最终的结果并不如人意,只是一些探索的过程记录。问题在于:当使用paramiko库时会提示openssh服务,而如果继续封装就有点违背当初的想法,应该有更优秀的解决方案。 提示信息说三遍,本文最终的结果并不如人意,只是一些探索的过程记录。问题在于:当使用paramiko库时会提示openssh服务,而如果继续封装就有点违背当初的想法,应该有更优秀的解决方案。 pipenv+virtualenv配置全新的python环境 如果需要用python写个项目,并且允许其运行在稍低版本的Linux下,需要构建一套完整的虚拟环境,这中间有许多坑,花了一个星期终于打包出来了。 总的来说, 首先需要构造完整的python环境 再构造一个虚拟环境以便于启动 打包相应的glibc包 执行指令时用绝对路径来运行命令。 全篇遇到了不少坑,主要依据这篇文章进行操作制作python虚拟环境包,大体上没有什么问题,但是更注重于操作,而缺少一些解释,以及没有glibc包的打包过程。 创建完整的python环境 如果只是用virtualenv或者pipenv等工具直接创建虚拟环境,那么虚拟环境中的很多.py文件都只是软连接指向系统自带的python环境对应的.py文件。 这样的话,即便虚拟环境ok了,在另一个python版本不对或者没有python环境的机器上就会找不到对应的位置而报错。 可以通过查看虚拟环境中的lib目录得知指向的位置, 所以在创建虚拟环境前需要创建完整的python环境。 由于那篇博客关于安装环境说得足够详细,所以这里不再赘述,请直接从制作python虚拟环境包的Centos换源到安装python进行操作,相关依赖最好直接安装好,包括zlib和openssl相关的依赖,前者主要作用在打包压缩,后者主要作用在加密解密。 tips:虽然理论上可以通过python2.6直接装2.7甚至3.x的python,但是由于版本古老,可能(大概率)python2.6下的virtualenv工具无法使用,因为python2.6不支持字典推导式,会报语法错误。尽量使用python2.7以上的版本。 tips2: centos6.x系统使用的是python2.6.6,centos7系统使用的是python2.7.5。 tips3: MacOSX上的/tmp并不是/tmp,而是/private/tmp。 python2.6安装pip,可以直接wget https://bootstrap.pypa.io/2.6/get-pip.py下载get-pip.py文件,然后python get-pip.py来安装 构造一个虚拟环境 在指定的目录创建好完整的python环境了,为什么还需要构造虚拟环境? 以我(浅薄的眼光)看来,安装好的python环境可以通过绝对路径调用,但是很多环境还是会调用系统自身的,这样会造成一种紊乱,我们需要用虚拟环境打包这个完整环境,给它换个皮,创建个单独的空间。 由于那篇博客关于安装虚拟环境说得足够详细,所以这里不再赘述,请直接看制作python虚拟环境包的虚拟环境操作进行操作,一般情况下会安装的特别快,如果出现了ImportError: No module named zlib那就是缺少zlib环境。 还记得前文提到的,“虚拟环境中的很多.py文件都只是软连接指向系统自带的python环境对应的.py文件”,此时我们再去看下虚拟环境的lib目录,可以看出虽然有指向,但指向的是之前安装的完整环境,所以理论上可以在任何Linux环境上使用。 打包glibc环境 一般情况下,创建完虚拟环境,就可以直接上传到测试机器,然后激活环境source .venv/bin/activate,然后执行项目入口文件就行了python run.py,如果不出错,那么就可以了,以下的步骤不用看了。 但是我的测试机系统是rhel6.7,会出现一个python: /lib64/libc.so.6: version 'GLIBC_2.14' not found (required by python)错误。 既然是/lib64/libc.so.6下报的错误,那么应该和glibc版本有关系。 通过查找资料,这篇文章解决libc.so.6: version `GLIBC_2.14’ not found问题写得足够详细,原因是系统的glibc版本太低,软件编译时使用了较高版本的glibc引起的,解决方法上面的文章也可以解决,注意将glib安装到之前设置的文件夹下,方便打包。 tips:一般我会将虚拟环境安装在.venv下,而将lib相关的包安装在.lib下 用绝对路径来运行命令 既然glibc也打包了,那么上传到测试机器,如何让python使用高版本的glibc而不使用系统自带的glibc? 直接思路当然是 export LD_LIBRARY_PATH=/YourDir/.lib/glibc-2.14/lib:$LD_LIBRARY_PATH 强制先使用自己制定的glibc,某些时候可以成功,某些时候会报另外一种错, python: error while loading shared libraries: __vdso_time: invalid mode for dlopen(): Invalid argument 通过查找StackFlow,发现了一个人的遭遇和我一摸一样,Error while using a newer version of glibc,给出的理由是export LD_LIBRARY_PATH覆盖的范围太广了,python不知道该使用哪一个glibc,按照给出的解决方案,测试过了并没有什么用。 ...

pip安装mysql-python出现的问题

Python Python Module pip安装mysql-python出现的问题 使用 pip 安装 mysql-python 这个包,总是会遇到各种问题,以我个人为例,就在 deepin linux,MacOSX,rhel6.7 上遇到过三次,这里主要针对的是 EnvironmentError: mysql_config not found 问题,解决方案来自于stackoverflow。 问题描述 (mysite)zjm1126@zjm1126-G41MT-S2:~/zjm_test/mysite$ pip install mysql-python Downloading/unpacking mysql-python Downloading MySQL-python-1.2.3.tar.gz (70Kb): 70Kb downloaded Running setup.py egg_info for package mysql-python sh: mysql_config: not found Traceback (most recent call last): File "<string>", line 14, in <module> File "/home/zjm1126/zjm_test/mysite/build/mysql-python/setup.py", line 15, in <module> metadata, options = get_config() File "setup_posix.py", line 43, in get_config libs = mysql_config("libs_r") File "setup_posix.py", line 24, in mysql_config raise EnvironmentError("%s not found" % (mysql_config.path,)) EnvironmentError: mysql_config not found Complete output from command python setup.py egg_info: sh: mysql_config: not found Traceback (most recent call last): File "<string>", line 14, in <module> File "/home/zjm1126/zjm_test/mysite/build/mysql-python/setup.py", line 15, in <module> metadata, options = get_config() File "setup_posix.py", line 43, in get_config libs = mysql_config("libs_r") File "setup_posix.py", line 24, in mysql_config raise EnvironmentError("%s not found" % (mysql_config.path,)) EnvironmentError: mysql_config not found ---------------------------------------- Command python setup.py egg_info failed with error code 1 Storing complete log in /home/zjm1126/.pip/pip.log (mysite)zjm1126@zjm1126-G41MT-S2:~/zjm_test/mysite$ pip install mysql-python Downloading/unpacking mysql-python Running setup.py egg_info for package mysql-python sh: mysql_config: not found Traceback (most recent call last): File "<string>", line 14, in <module> File "/home/zjm1126/zjm_test/mysite/build/mysql-python/setup.py", line 15, in <module> metadata, options = get_config() File "setup_posix.py", line 43, in get_config libs = mysql_config("libs_r") File "setup_posix.py", line 24, in mysql_config raise EnvironmentError("%s not found" % (mysql_config.path,)) EnvironmentError: mysql_config not found Complete output from command python setup.py egg_info: sh: mysql_config: not found Traceback (most recent call last): File "<string>", line 14, in <module> File "/home/zjm1126/zjm_test/mysite/build/mysql-python/setup.py", line 15, in <module> metadata, options = get_config() File "setup_posix.py", line 43, in get_config libs = mysql_config("libs_r") File "setup_posix.py", line 24, in mysql_config raise EnvironmentError("%s not found" % (mysql_config.path,)) EnvironmentError: mysql_config not found ---------------------------------------- Command python setup.py egg_info failed with error code 1 Storing complete log in /home/zjm1126/.pip/pip.log 解决方案 Debian/Ubuntu sudo apt-get install libmysqlclient-dev 新版本(比如2018)的 Debian/Ubuntu ...

pyconcrete的简单学习

Python Python Module pyconcrete 的简单学习 pypi-pyconcrete 0.12.1 (个人感觉用这个库加密 python 程序的人不多。。。) (我在 MacOS python3.7.3 下又无法安装了) pyconcrete 是一个 python 文件加密库,它可以将常规的 .py 文件或 .pyc 文件加密为 .pye 文件,这样就无法直接打开源代码,避免了源代码的泄漏,也为 python 项目商用提供了解决方案。 该库在国内用的人不多,中文教程也少得可怜,Google 首页就两篇中文相关内容,一篇还是认识的人写的,一篇是对 GitHub 上对应项目的自述文件进行机翻,这里参考的是Falldog/pyconcrete。 安装 尽量不要使用 pip 安装!!! 我的几次安装经历,通过 pip 安装总是会出现各种各样的问题,可以试着通过 $ pip install pyconcrete --egg --install-option="--passphrase=<your passphrase>" 进行安装,或者下载源代码,进行安装,这可能是最快的安装方式。 保护你的 python 代码工作流 在 your_script.py 首行 import pyconcrete pyconcrete 将会自动和其他模块挂钩 当 your_script.py 开始导入其他模块,pyconcrete 首先会尝试寻找 MODULE.pye,然后通过 _pyconcrete.pyd 对MODULE.pye 进行解密 执行加密后的文件。 加密 只支持 AES 128 位加密 通过 OpenAES 加解密 用法 完整加密 将所有以 .py 结尾的文件转为 .pye。 $ pyconcrete-admin.py compile --source=<your py script> --pye $ pyconcrete-admin.py compile --source=<your py module dir> --pye 移除所有的 *.py 和 *.pyc 文件,或者将所有的 *.pye 文件移动到其他的文件夹 main.py 文件也会被加密为 main.pye,它无法被普通的 python 直接调用。必须使用 pyconcrete 来启动 main.pye。 pyconcrete main.pye src/*.pye # your libs 部分加密 将库文件被部分加密。 ...

pytest的简单学习

Pytest 的简单学习 一、介绍及下载安装 [[Pytest]] 是 [[Python]] 的一种单元测试框架,与 python 自带的 unittest 测试框架类似,但是比 unittest 框架使用起来更简洁,效率更高。 其主要使用 assert 断言对单元方法记性测试 其有个 fixture 类,可以减少资源占用,资源的统一调度 安装:pip install -U pytest 测试: py.test --version 或者 pytest --version 二、基础单元测试(assert 断言) assert 断言是 python 标准语法里的东西 asset 后是一个返回布尔值的表达式 若为真,则通过;若为假,抛出异常 # example >>>assert 1 == 1 >>>assert 2+2 == 2*2 >>>assert len('hello') < 10 >>>assert len('hello') > 10 Traceback (most recent call last): File "<stdin>", line 1, in <module> AssertionError >>>assert len('hello') > 10, '字符串长度小于10' Traceback (most recent call last): File "<stdin>", line 1, in <module> AssertionError: 字符串长度小于10 >>>assert range(4) == [0,1,2,3] 通过上面关于 assert 的例子,可以看出很适合单元测试。 ...

Python打包文件夹

使用[[Python]]对指定目录进行打包。 zip import os, zipfile #打包目录为zip文件(未压缩),空目录会被忽略 def make_zip(source_dir, output_filename): zipf = zipfile.ZipFile(output_filename, 'w') pre_len = len(os.path.dirname(source_dir)) for parent, dirnames, filenames in os.walk(source_dir): for filename in filenames: pathfile = os.path.join(parent, filename) arcname = pathfile[pre_len:].strip(os.path.sep) #相对路径 zipf.write(pathfile, arcname) zipf.close() tar/tar.gz import os, tarfile #一次性打包整个根目录。空子目录会被打包。 #如果只打包不压缩,将"w:gz"参数改为"w:"或"w"即可。 def make_targz(output_filename, source_dir): with tarfile.open(output_filename, "w:gz") as tar: tar.add(source_dir, arcname=os.path.basename(source_dir)) import os, tarfile #逐个添加文件打包,未打包空子目录。可过滤文件。 #如果只打包不压缩,将"w:gz"参数改为"w:"或"w"即可。 def make_targz_one_by_one(output_filename, source_dir): tar = tarfile.open(output_filename,"w:gz") for root,dir,files in os.walk(source_dir): for file in files: pathfile = os.path.join(root, file) tar.add(pathfile) tar.close()

Schema库的简单学习

Python Python Module Schema 库的简单学习 Schema 是一个简单易用的 python 数据校检三方库,Schema on Github. 在 web app 中,经常需要接收用户传过来的数据,然后做处理。但是用户由于各种原因,输入的数据并不如人意。前端发送 json 形式数据到后端 api,以往的解决方案甚是暴力,对 json 的 key 的值进行各种 if 检验,甚至要去做正则匹配。使用 schema 库能够非常优雅的解决这个问题。 Schema 和 marshmallow 的取舍。之前学习过 marshmallow,它有一个方法Schema.validate,同样可以完成数据校检,但是需要先生成一个独特的 Schema 类,用起来更适合序列化/反序列化的场景。而 Schema 库只做一件事,那就是数据校检。 核心类 Schema 数据检验最重要的类 Regex 正则匹配检验用到的类 Use And Or 一个类、一个方法 这是 schema 库里最重要的概念。 一个类是 Schema 类,可以理解为 schema 库的入口,什么都可以往里面传。 一个方法是 validate 方法,它接入一个数据或者一个 obj。 执行校检就是处理 validate 接收的数据和 Schema 类接收的 schema 之间的关系。 Schema 类传入基础类型 str,int,float,object >>> from schema import Schema >>> Schema(str).validate('abc') 'abc' >>> Schema(int).validate(123) 123 >>> Schema(float).validate(1.23) 1.23 >>> Schema(object).validate('abcd') 'abcd' >>> Schema(str).validate(123) schema.SchemaUnexpectedTypeError: 123 should be instance of 'str' 基础类型没什么好说的,只能检验最简单的数据。注意 object 是基类,也就是 validate 里的数据符合语法就会原样输出,但我们可以基于此做些类的判断 ...

timeit模块的使用

Python Python Module timeit模块的使用 timeit 主要是为了测试代码运行速度。 它主要有两个方法,即 timeit 和 repeat。 测试一段代码的运行时间,在 python 里面有个很简单的方法,就是使用 timeit 模块,使用起来超级方便 下面简单介绍一个 timeit 模块中的函数。 主要就是这两个函数: timeit(stmt='pass', setup='pass', timer=<defaulttimer>, number=1000000) 返回: 返回执行stmt这段代码number遍所用的时间,单位为秒,float型 参数: stmt:要执行的那段代码 setup:执行代码的准备工作,不计入时间,一般是import之类的 timer:这个在win32下是time.clock(),linux下是time.time(),默认的,不用管 number:要执行stmt多少遍 repeat(stmt='pass', setup='pass', timer=<defaulttimer>, repeat=3, number=1000000) 这个函数比 timeit 函数多了一个 repeat 参数而已,表示重复执行 timeit 这个过程多少遍,返回一个列表,表示执行每遍的时间。 当然,为了方便,python 还用了一个 Timer 类,Timer 类里面的函数跟上面介绍的两个函数是一样一样的 class timeit.Timer(stmt='pass', setup='pass',timer=<timer function>) Timer.timeit(number=1000000) Timer.repeat(repeat=3,number=1000000) 看懂了吧,一样的,使用的时候哪种方便用哪种。 就相当于 timeit(stmt='pass', setup='pass', timer=<defaulttimer>, number=1000000) = Timer(stmt='pass', setup='pass', timer=<timerfunction>).timeit(number=1000000) repeat(stmt='pass', setup='pass', timer=<defaulttimer>, repeat=3, number=1000000) = Timer(stmt='pass', setup='pass', timer=<timerfunction>).repeat(repeat=3, number=1000000)