使用github+travis将Python包部署到Pypi

我在 github 托管 Python 代码,然后将包发布到 Pypi,通常的操作步骤是,更新完代码将提交到 github ,然后手动将包更新到 pypi,这样比较繁琐,就想到了使用github+travis-ci 构建一个自动部署环境。 注册 pypi 访问https://pypi.org 点击Register注册账号,记住自己的用户名密码。 创建 setup.py 文件 setup.py 文件放置于包的根目录,示例内容如下: #!/usr/bin/env python from setuptools import setup, find_packages with open("README.md", "r") as fh: long_description = fh.read() with open('requirements.txt') as f: requirements = [l for l in f.read().splitlines() if l] setup(name="python-weixin", # 项目名 version="0.3.2", # 版本号 description="Python Weixin API client support wechat-app", #简介 long_description=long_description, # 长简介 这里使用的 readme 内容 long_description_content_type="text/markdown", license="BSD", # 授权 install_requires=requirements, # 依赖 author="gusibi", # 作者 author_email="[email protected]", # 邮箱 url="https://github.com/gusibi/python-weixin", # 地址 download_url="https://github.com/gusibi/python-weixin/archive/master.zip", packages=find_packages(), keywords=["python-weixin", "weixin", "wechat", "sdk", "weapp", "wxapp"], zip_safe=True) 以上特别需要注意的是 packages参数,用来申明你的包里面要包含的目录,这里使用setuptools自动决定要包含哪些包。 ...

2018-07-23 · 2 min · 308 words

Python 生成便签图片

最近有文字转图片的需求,但是不太想下载 APP,就使用 Python Pillow 实现了一个,效果如下: PIL 提供了 PIL.ImageDraw.ImageDraw.text 方法,可以方便的把文字写到图片上,简单示例如下: from PIL import Image, ImageDraw, ImageFont # get an image base = Image.open('Pillow/Tests/images/hopper.png').convert('RGBA') # make a blank image for the text, initialized to transparent text color txt = Image.new('RGBA', base.size, (255,255,255,0)) # get a font fnt = ImageFont.truetype('Pillow/Tests/fonts/FreeMono.ttf', 40) # get a drawing context d = ImageDraw.Draw(txt) # draw text, half opacity d.text((10,10), "Hello", font=fnt, fill=(255,255,255,128)) # draw text, full opacity d.text((10,60), "World", font=fnt, fill=(255,255,255,255)) out = Image.alpha_composite(base, txt) out.show() 为什么要计算文字的宽高呢?把文字直接写到背景图不可以么? ...

2018-07-08 · 3 min · 469 words

Python gRPC 入门

gRPC 一开始由 google 开发,是一款语言中立、平台中立、开源的远程过程调用(RPC)系统。 本文通过一个简单的 Hello World 例子来向您介绍 gRPC 。 gRPC 是什么? gRPC 也是基于以下理念:定义一个服务,指定其能够被远程调用的方法(包含参数和返回类型)。在服务端实现这个接口,并运行一个 gRPC 服务器来处理客户端调用。在客户端拥有一个存根能够像服务端一样的方法。 在 gRPC 里客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端应用的方法,使得我们能够更容易地创建分布式应用和服务。 gRPC 客户端和服务端可以在多种环境中运行和交互,并且可以用任何 gRPC 支持的语言来编写。 gRPC 支持 C++ Java Python Go Ruby C# Node.js PHP Dart 等语言 gRPC 默认使用 protocol buffers,这是 Google 开源的一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。 安装 Google Protocol Buffer 方法一(建议使用) 参考文档:gRPC Python Quickstart 1. 安装 gRPC python -m pip install grpcio # 或者 sudo python -m pip install grpcio # 在 El Capitan OSX 系统下可能会看到以下报错 $ OSError: [Errno 1] Operation not permitted: '/tmp/pip-qwTLbI-uninstall/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/six-1.4.1-py2.7.egg-info' # 可以使用以下命令 python -m pip install grpcio --ignore-installed 2. 安装 gRPC tools Python gPRC tools 包含 protocol buffer 编译器和用于从 .proto 文件生成服务端和客户端代码的插件 ...

2018-06-07 · 3 min · 626 words

Python 字典

这一篇是《流畅的 python》读书笔记。主要介绍: 常见的字典方法 如何处理查不到的键 标准库中 dict 类型的变种 散列表的工作原理 泛映射类型 collections.abc 模块中有 Mapping 和 MutableMapping 这两个抽象基类,它们的作用是为 dict 和其他类似的类型定义形式接口。 标准库里所有映射类型都是利用 dict 来实现的,它们有个共同的限制,即只有可散列的数据类型才能用做这些映射里的键。 问题: 什么是可散列的数据类型? 在 python 词汇表(https://docs.python.org/3/glossary.html#term-hashable)中,关于可散列类型的定义是这样的: 如果一个对象是可散列的,那么在这个对象的生命周期中,它的散列值是不变的,而且这个对象需要实现 __hash__() 方法。另外可散列对象还要有 __eq__() 方法,这样才能跟其他键做比较。如果两个可散列对象是相等的,那么它们的散列只一定是一样的 根据这个定义,原子不可变类型(str,bytes和数值类型)都是可散列类型,frozenset 也是可散列的(因为根据其定义,frozenset 里只能容纳可散列类型),如果元组内都是可散列类型的话,元组也是可散列的(元组虽然是不可变类型,但如果它里面的元素是可变类型,这种元组也不能被认为是不可变的)。 一般来讲,用户自定义的类型的对象都是可散列的,散列值就是它们的 id() 函数的返回值,所以这些对象在比较的时候都是不相等的。(如果一个对象实现了 eq 方法,并且在方法中用到了这个对象的内部状态的话,那么只有当所有这些内部状态都是不可变的情况下,这个对象才是可散列的。) 根据这些定义,字典提供了很多种构造方法,https://docs.python.org/3/library/stdtypes.html#mapping-types-dict 这个页面有个例子来说明创建字典的不同方式。 >>> a = dict(one=1, two=2, three=3) >>> b = {'one': 1, 'two': 2, 'three': 3} >>> c = dict(zip(['one', 'two', 'three'], [1, 2, 3])) >>> d = dict([('two', 2), ('one', 1), ('three', 3)]) >>> e = dict({'three': 3, 'one': 1, 'two': 2}) >>> a == b == c == d == e True 除了这些方法以外,还可以用字典推导的方式来建造新 dict。 ...

2017-12-03 · 3 min · 568 words

使用腾讯云配置小程序Python开发环境

最近做小程序服务器的配置,这一篇是服务器配置的记录,方便以后安装配置。 购买服务器 之所以选腾讯云的原因很简单,那就是便宜,选用成都区,最低配置每月只需29¥。 在 腾讯云 官网注册登录就可以直接购买服务器了。 服务器系统我选择的是 ubuntu。 服务器配置 启动服务后使用新用户(此步骤不是必须)。 新建用户 首先确认使用的是 root 用户登录如果不是使用以下命令切换 sudo su 使用 adduser 命令创建用户 adduser username # username替换为你自己的用户名 接下来的步骤会让你输入密码和个人信息,自己设置就好。 使用usermod 命令将新建的用户添加到 sudo 组。 usermod -aG sudo username 关闭ssh密码登录使用密钥登录 安装openssh 因为是新系统,先执行一下 apt-get update sudo apt-get update sudo apt-get install openssh-server 启动ssh服务 可以通过sudo su命令来临时切换到root权限(不是所有的账号都可以切换到root权限,只有在/etc/sudoers文件中符合规则的用户能切换root身份) sudo su /etc/init.d/ssh start 使用密钥登录 服务器端生成密钥对: cd /home/gs # 打开新建的用户目录 mkdir .ssh cd .ssh ssh-keygen -b 2048 -t rsa ssh-keygen的基本用法: -b后面是指定加密后的字符串长度 -t后面是指定加密算法,常用的加密算法有rsa,dsa等 默认生成的文件如下: id_rsa.pub # 公钥文件 id_rsa # 私钥文件 新建 authorized_keys 文件 将本地机器的 id_rsa.pub 文件内容复制到 authorized_keys 文件 ...

2017-10-21 · 3 min · 471 words

Python 元组和分片

这一篇是《流畅的 python》读书笔记。主要介绍元组、分片、序列赋值以及引用了大师 Edsger W.Dijkstra为什么序列从0开始计数的解释。 元组 在有些python 的介绍中,元组被称为不可变列表,这其实是不准确的,没有完全概括元组的特点。元组除了用作不可变列表,还可以用于没有字段名的记录。 元组和记录 元组其实是对数据的记录:元组中的每个元素都存放了记录中一个字段的数据,外加这个数据的位置。 如果把元组当作一些字段的集合,数量和位置信息会变得非常重要。比如以下几条用元组表示的记录: >>> lax_coordinates = (33.9425, -118.408056) # 洛杉矶国际机场的经纬度 # 东京的一些信息:市名、年份、人口、人口变化和面积 >>> city, year, pop, chg, area = ('Tokyo', 2003, 32450, 0.66, 8014) 以上这两个元组每个位置都对应一个数据记录。 元组拆包 >>> city, year, pop, chg, area = ('Tokyo', 2003, 32450, 0.66, 8014) 这个例子中,我们把元组的数据用一条语句分别赋值给 city, year, pop, chg, area,这就是元组拆包的一个具体应用。 元组拆包可以应用到任何可迭代对象上,但是被迭代的对象窄的元素的数量必须跟接受这些元素的元组的空档数一致。 比如: >>> lax_coordinates = (33.9425, -118.408056) >>> latitude, longitude = lax_coordinates >>> latitude 33.9425 >>> longitude -118.408056 还可以用 * 运算符把一个可迭代对象拆开作为函数的参数: >>> divmod(20, 8) (2, 4) >>> t = (20, 8) >>> divmode(*t) (2, 4) >>> quotient, remainder = divmode(*t) >>> quotient, remainder (2, 4) 在进行拆包是,我们可能对元组的某些值并不感兴趣,这时可以用 _ 占位符处理。比如: ...

2017-09-10 · 3 min · 583 words

Python 列表推导及优先级队列的实现

这一篇是《流畅的 python》读书笔记。主要介绍列表、列表推导有关的话题,最后演示如何用列表实现一个优先级队列。 Python 内置序列类型 Python 标准库用 C 实现了丰富的序列类型: 容器序列: list、tuple 和 collections.deque 这些序列能存放不同类型的数据。 扁平序列: str、bytes、bytearray、memoryview 和 array.array,这类序列只能容纳一种类型。 容器序列存放的是它们所包含的任意类型的对象的引用,而扁平序列里存放的是值而不是引用(也可以说扁平序列其实存放的是一段连续的内存空间)。 如果按序列是否可被修改来分类,序列分为可变序列 和 不可变序列: 可变序列 list、bytearray、array.array、collections.deque 和 memoryview。 不可变序列 tuple、str和 bytes。 下图显示了可变序列(MutableSequence)和不可变序列(sequence)的差异: 从这个图可以看出,可变序列从不可变序列那里继承了一些方法。 列表推导和生成器表达式 列表(list)是 Python 中最基础的序列类型。list 是一个可变序列,并且能同时存放不同类型的元素。 列表的基础用法这里就不再介绍了,这里主要介绍一下列表推导。 列表推导和可读性 列表推导是构建列表的快捷方式,并且有更好的可读性。 先看下面两段代码: #1. 把一个字符串变成 unicode 码位的列表 >>> symbols = '$&@#%^&*' >>> codes = [] >>> for symbol in symbols: codes.append(ord(symbol)) >>> codes [36, 38, 64, 35, 37, 94, 38, 42] #2. 把一个字符串变成 unicode 码位的列表 使用列表推导 >>> symbols = '$&@#%^&*' >>> codes = [ord(s) for s in symbols] >>> codes [36, 38, 64, 35, 37, 94, 38, 42] 对比发现,如果理解列表推导的话,第二段代码比第一段更简洁可读性也更好。 当然,列表推导也不应该被滥用,通常的原则是只用列表推导来创建新的列表,并且尽量保持简短。 如果列表推导超过两行,就应该考虑要不要使用 for 循环重写了。 ...

2017-09-03 · 3 min · 583 words

小程序开发:上传图片到腾讯云

这是小程序开发第二篇,主要介绍如何上传图片到腾讯云,之所以选择腾讯云,是因为腾讯云免费空间大😂 准备工作 上传图片主要是将图片上传到腾讯云对象存储(COS)。 要使用对象存储 API,需要先执行以下步骤: 购买腾讯云对象存储(COS)服务 在腾讯云 对象存储控制台 里创建一个 Bucket 在控制台 个人 API 密钥 页面里获取 AppID、SecretID、SecretKey 内容 编写一个请求签名算法程序(或使用任何一种服务端 SDK) 计算签名,调用 API 执行操作 所以我们要做的准备工作有: 进入腾讯云官网,注册帐号 登录云对象存储服务(COS)控制台,开通COS服务,创建资源需要上传的Bucket 在小程序官网上配置域名信息(否则无法在小程序中发起对该域名的请求) 这些配置过程这里就不做说明了,接下来主要介绍步骤4、5。 小程序上传图片到 cos 流程如下图: 在这个过程中我们需要实现的是,鉴权服务器返回签名的步骤以及小程序的相关步骤。 COS鉴权服务 使用对象存储服务 COS 时,可通过 RESTful API 对 COS 发起 HTTP 匿名请求或 HTTP 签名请求,对于签名请求,COS 服务器端将会进行对请求发起者的身份验证。 匿名请求:HTTP 请求不携带任何身份标识和鉴权信息,通过 RESTful API 进行 HTTP 请求操作。 签名请求:HTTP 请求时添加签名,COS服务器端收到消息后,进行身份验证,验证成功则可接受并执行请求,否则将会返回错误信息并丢弃此请求。 腾讯云COS对象存储,基于密钥 HMAC (Hash Message Authentication Code) 的自定义 HTTP 方案进行身份验证。 上传图片是一个签名请求,需要进行签名验证。之所以我们 签名流程 客户通过对 HTTP 请求进行签名,并将签名后的请求发送至腾讯云进行签名验证,具体流程如下图所示。 我们使用 sdk 开发,这个流程大致了解下就行,签名的实现 sdk 已经包含,只需要调用方法即可。 ...

2017-08-27 · 3 min · 461 words

Python 装饰器使用指南

装饰器是可调用的对象,其参数是另一个函数(被装饰的函数)。 装饰器基础知识 首先看一下这段代码 def deco(fn): print "I am %s!" % fn.__name__ @deco def func(): pass # output I am func! # 没有执行func 函数 但是 deco 被执行了 HUGOMORE42 在用某个@decorator来修饰某个函数func时 @decorator def func(): pass 其解释器会解释成下面这样的语句: func = decorator(func) 其实就是把一个函数当参数传到另一个函数中,然后再回调,但是值得注意的是装饰器必须返回一个函数给func 装饰器的一大特性是,能把被装饰的函数替换成其他函数。第二大特性是,装饰器在加载模块时立即执行。 装饰器何时执行 装饰器的一个关键特性是,它们在被装饰的函数定义后立即运行。这通常在导入是(python 加载模块时)。 看下下面的示例: registry = [] # registry 保存被@register 装饰的函数的引用 def register(func): # register 的参数是一个函数 print('running register(%s)' % func) # 打印被装饰的函数 registry.append(func) # 把 func 存入 `registery` return func # 返回 func:必须返回函数,这里返回的函数与通过参数传入的一样 @register # `f1` 和 `f2`被 `@register` 装饰 def f1(): print('running f1()') @register def f2(): print('running f2()') def f3(): # <7> print('running f3()') def main(): # main 打印 `registry`,然后调用 f1()、f2()和 f3() print('running main()') print('registry ->', registry) f1() f2() f3() if __name__=='__main__': main() # <9> 运行代码结果如下: ...

2017-08-15 · 8 min · 1578 words

自定义 Sanic Exception

Sanic 是一个和类Flask 的基于Python3.5+的web框架,它使用了 Python3 异步特性,有远超 flask 的性能。 编写 RESTful API 的时候,我们会定义特定的异常错误类型,比如我定义的错误返回值格式为: { "error_code": 0, "message": "string", "text": "string" } 不同的错误信息指定不同的 http 状态码。 sanic 提供了几种常用的 exception: NotFound(404) Forbidden(403) ServerError(500) InvalidUsage(400) Unauthorized(401) RequestTimeout(408) PayloadTooLarge(413) 这些 exception 继承自 SanicException 类: class SanicException(Exception): def __init__(self, message, status_code=None): super().__init__(message) if status_code is not None: self.status_code = status_code 从上述代码可以看出,这些异常只能指定 message 和 status_code 参数,那我们可不可以自定义 exception 然后在自定义的 exception 中增加参数呢?下面的代码是按照这个思路修改后的代码: class ApiException(SanicException): def __init__(self, code, message=None, text=None, status_code=None): super().__init__(message) self.error_code = code self.message = message self.text = text if status_code is not None: self.status_code = status_code 使用后我得到一个结果如下: ...

2017-08-05 · 2 min · 395 words