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 [[OOP]] Python 新式类和旧式类 新式类从 python2.2 开始引入。 定义区别 # python2.x class A: # 旧式类 pass class B(object): # 新式类 pass class C(A): # 旧式类,因为 A 是旧式类 pass class D(B): # 新式类 pass class E(A, B): # 新式类 pass class F(B, A): # 新式类 # python3.x class A: # python3.x 全是新式类 pass 使用区别 __class__ 执行结果和type不一致 继承搜索的顺序 __slots__ __getattribute__ 对新式类的实例执行 a.__class__ 与 type(a) 的结果是一致的,对于旧式类来说就不一样了。 >>> class A: ... pass >>> a = A() >>> a <__main__.A instance at 0x10654bc68> >>> a.__class__ <class __main__.A at 0x1064cec18> >>> type(a) <type 'instance'> >>> class B(object): ... pass ... >>> b = B() >>> b.__class__ <class '__main__.B'> >>> type(b) <class '__main__.B'> 继承搜索的顺序 class A(): def __init__(self): pass def save(self): print "This is from A" class B(A): def __init__(self): pass class C(A): def __init__(self): pass def save(self): print "This is from C" class D(B,C): def __init__(self): pass fun = D() fun.save() 经典类的答案: This is from A 新式类的答案: This is from C ...

python 类的实例化的全过程

Python [[OOP]] python 类的实例化的全过程 开篇 一直以来使用 Python 里的类,都是先写类名,然后 __init__, 并且 Python 变量不需要声明类型的,就理所应当的觉得 Python 里没有 new,不像是 Java 或者 C# 那样使用一个对象前要先 new 一个出来,然后再实例化。 结果是 Python 里有 __new__ 这个概念,但是大部分情况下会被隐藏,我们可以先定义一个类,然后 dir(cls) 看下有哪些方法。 __new__ 是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解,在 Python 中存在于类里面的构造方法 __init__ 负责将类的实例化,而在 __init__ 启动之前,__new__ 决定是否要使用该 __init__ 方法,因为 __new__ 可以调用其他类的构造方法或者直接返回别的对象来作为本类的实例。 如果将类比喻为工厂,那么 __init__ 方法则是该工厂的生产工人,__init__ 方法接受的初始化参数则是生产所需原料,__init__ 方法会按照方法中的语句负责将原料加工成实例以供工厂出货。而 __new__ 则是生产部经理,__new__ 方法可以决定是否将原料提供给该生产部工人,同时它还决定着出货产品是否为该生产部的产品,因为这名经理可以借该工厂的名义向客户出售完全不是该工厂的产品。 __new__() 方法的特性: __new__() 方法是在类准备将自身实例化时调用。 __new__() 方法始终都是类的静态方法,即使没有被加上静态方法装饰器。 new 和 init 先来定义个类: class Test(object): def __init__(self, *args, **kwargs): print("in init...") test = Test() 上述代码会输出一句 “in init”,但是它隐藏了对 __new__ 的调用,再来定义个类。 ...

Python 连接 MySQL

MySQL database Python Python 连接 MySQL 使用接口 Python DB API,两种情况: python2.7,使用 Python-MySQL connector,载入语句 import MySQLdb python3.4,安装 pymysql 模块,载入语句 import pymysql Connection对象: 创建方法:pymysql.Connect(host,port,user,passwd,db) 支持方法: 1、cursor(),使用该连接创建并返回游标 2、commit(),提交当前事务 3、rollback(),回滚当前事务 4、close(),关闭连接 cursor游标对象:用于执行查询和获取结果 支持方法: 1、execute(op,[args]),执行一个数据库查询和命令 2、fetchone(),取得结果集的下一行 3、fetchmany(size),取得结果集的下几行 4、fetchall(),取得结果集的剩下的所有行 5、rowcount,最近一次execute返回数据的行数或影响行数 6、close(),关闭游标对象 select查询数据操作过程 开始 创建connection 创建cursor 使用cursor.excute()执行select语句 使用cursor.fetch*()获取并处理数据 关闭cursor 关闭connection -结束 insert/update/delete更新数据库操作过程 开始 创建connection 创建cursor 使用cursor.excute()执行insert/update/delete语句 -出现异常:使用connection.rollback()回滚事务 未出现异常:使用connection.commit()提交事务 关闭cursor 关闭connection 结束

Python2 字符串问题

Python Python2 字符串问题 原谅我这一生不羁放纵爱自由 也会怕有一天会跌倒 Hoo No 字符串在python中的使用很多,而且字符串也很多种类,本身也有很多方法,例如replace,len,startswith,endwith,split等等,本文着重于字符串和编码之间的关系。 Python2 的字符串,一般不会出问题,遇到中英文混编的时候就会很糊涂,查了些资料,由于时代的限制,当时的字符串设计仅对纯英文友好,更不必谈混编,后来的 2.7.x 版本已经做的很好了,但是真遇到问题会比较绕,内部的处理机制完全不符合 Python 设计哲学的 Simple is better than complex。 关于字符编码的历史问题,已经目前常用的编码以及转换,可以看字符串和编码。 归根结底:str其实并不是字符串而是字节串(八位二进制数据串),而Unicode字符串对象才是真正的字符串。 总结的解决方案为:读取到字节串数据后根据实际编码格式解码(decode)成 Unicode 字符串对象,使用 Unicode 对象处理字符串,输出到控制台时用 Unicode 字符串对象,保存数据到文件时将字符串编码(encode)成 utf-8 编码格式字节串数据。如果是代码里面创建的字符串对象,遇到中英文混排的情况,尽量使用 Unicode 来避免 UnicodeEncodeError。 更多的文章可以参考: Python2字符串编码问题总结 Python2和Python3之间关于字符串编码处理的差别

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 里的数据符合语法就会原样输出,但我们可以基于此做些类的判断 ...