Python脚本共享小技巧
作为一名python程序员,在日常工作中,面对各种错中复杂的场景,总能用几行代码快速解决一些问题。当然有些是临时的,跑一次就被 shift + delete 了, 有一些是需要隔三差五的跑一次的,比如每月一次的数据修正脚本,每天一次的数据分析统计脚本等,甚至还有一些问题排查脚本,运营人员会不定时的过来询问,每次都需要执行一次。面对这些大量的执行需求,不可能每次都要自己去打开电脑去操作,程序员的时间是宝贵的,不能总浪费在这些重复工作中,有没有办法可以让其他人员可以执行我们的脚本呢,答案是肯定的,本文就来讲讲我的python脚本共享之路。
思路1:共享机器
把脚本部署到一台公共机器上,给同事一个使用手册,让大家自己按照手册去使用。事实上我的第一个版本就是这样的,使用手册如下:
**排查问题脚本使用手册 **
ssh www-data@10.103.104.164 密码 ****
source yanjie/pythonEnv/script/bin/activate
cd yanjie/git/script/galaxy/
python agent_retailer.py 123
复制代码
但使用一段时间后, 使用者纷纷发来吐槽,说操作太复杂, 既要记地址又要记密码,还要去输入一些根本看不懂的命令,太难用,于是很快放弃了。
思路2:借助webssh快速登陆机器
鉴于第一种方案的吐槽,我闲暇之余,找了一些开源的webssh工具,比如:GateOne、Webssh2、WebSSH等。但在自己搭建完成体验一番后,发现操作更加复杂,依然需要使用者熟悉linux命令,而且登陆者拥有root权限存在极大的操作风险,方案直接pass,继续寻找其他方案。
这里强烈推荐一下Webssh, 一个纯python版实现的项目。
github地址:github.com/xsank/webss…
思路3: 提供网页操作
在前两种技术人员思想方案相继失败后,我又回到了原点,以使用者的角度去分析这个问题,他们需要的只是一个简单的界面,随便点点就能出结果。
问题1: 如何才能做到做到用户可视化操作?
很快,基于Flask实现一个网页版,使用ajax进行数据传输,操作简单,功能可用,但存在一个问题,我的脚本是有很多个过程,只有跑完全部流程才会返回全部内容, 当脚本运行耗时较多时,用户就会处于一个傻等状态,此时,使用者就会以为系统有问题,不停的点击重试。
问题2: 如何才能做到脚本内容的分段式输出?
最直接的办法,就是讲脚本请求分成多个ajax来做,但因实现成本过高,pass。好在之前有过webssh的调研,这里直接想到了借助websocket进行实现,这样在脚本参数固定的情况下就不用改与前端的交互层。于是就基于flask-socketio实现了一版:
# coding: utf-8
from prettytable import PrettyTable
from flask_socketio import SocketIO, send, emit
socketio = SocketIO(app, async_mode='threading')
# 这里为了方便使用 threading 模式,还有 eventlet、gevent 两种可选模式
def send_msg(event=None, title=None, table_obj=None):
""""""
table_attrs = {"class": "table table-bordered table-hover small text-center"}
title = html_p(title) if title else ''
content = ''
if isinstance(table_obj, six.text_type):
content = html_p(table_obj)
elif isinstance(table_obj, PrettyTable):
content = table_obj.get_html_string(attributes=table_attrs) \
if table_obj and len(table_obj._rows) > 0 else u'无记录'
if event is None:
send(title + content)
else:
emit(event, title + content)
@socketio.on('agent_retailer')
def handle_agent_retailer(json):
""""""
event = 'agent_retailer'
retailer_id = json['retailer_id']
send_msg(event, u'查询商户信息:', agent_retailer.search_retailer_info(retailer_id))
send_msg(event, u'查询当前主承运商:', agent_retailer.search_current_agents(retailer_id))
复制代码
问题3: 如何才能优雅的输出脚本内容
为了实现本地脚本与web输出的一致性及优雅性,这里借助了 PrettyTable 库进行格式化
# coding: utf-8
from prettytable import PrettyTable
def search_retailer_info(retailer_id):
"""查询基本信息"""
print(u'当前主承运商:')
x = PrettyTable([u'ID', u'名称', u'所在城市', u'采购服务'])
x.add_row([
retailer_id,
u'张三',
u'上海',
u'服务1'
])
print(x)
return x
def search_current_agents(retailer_id):
""""""
print(u'当前主承运商:')
x = PrettyTable([u'商户ID', u'商户名称', u'网格ID', u'主承运商', u'绑定时间'])
x.add_row([
retailer_id,
u'张三',
1,
u'李四',
arrow.now().date()
])
print(x)
return x
复制代码
效果演示:
以上就是关于如何方便快速的实现python脚本的共享化方案,Demo源码可在github中查看: