python代码模拟下拉_python基于windows自动下拉git代码并重启程序模块。

前言:

笔者最近在搞一个项目,需要把python客户端代码(可以理解成绑定不同账号的爬虫吧)部署在20+台windows机器上(以后还会追加新机器)。由于客户机多,而且常常优化、修bug、加功能,使得笔者为了更新代码而不胜其扰!小小的调整居然要一台台搞(windows只能远程连接,你懂的,可没办法linux那样同时给多个ssh连接发相同的命令)。于是,笔者测试并开发了一套“基于windows自动下拉git代码并重启程序模块”(笔者不知道该简称什么...大概就是自动更新代码吧)。

思路:

linux系统就不多说了,只需要git检测到更新后,kill -9 掉即可,可以根据参数识别,例如 python client_main.py 利用ps筛选出来干掉即可。

windows没有这命令,但是可以根据执行文件名杀掉。例如杀掉名叫 python.exe 的所有进程。这是唯一方法,但是你会把系统下所有的python都干掉,包括基于python的调试工具。

于是,我想到的方法是用最土的方法,“用标识位告知程序是否有更新,是否要介绍,是否要重启”。233333虽然又土又不帅气,却很实用。特别像我这种客户端必须等一个任务完成后才能终结的,非常合适。一个守护进程检测更新,一个文件标识状态,子进程自己检测标识状态去停止。简简单单的完成了自动化需求。

代码:

测试git仓库 : https://gitee.com/kid0/tx 【有需要测试,代码请上传到自己的git上方便测试。当然也可以在自己的git项目中直接引用auto.py下的函数】

模块代码(我命名为auto.py)

#-*-coding:utf-8-*-

import os

import time

import codecs

from configparser import ConfigParser

from multiprocessing import Process

local_path = os.path.join(os.getcwd(),'local.txt' )

code_check_time = 10

def set_code_check_time(t=10):

"""

设置git检测频率,单位秒

"""

global code_check_time

code_check_time = t

def auto_manager_main(fun,*args,**kwargs):

"""

委托进程

"""

print('主进程PID:',os.getpid())

global code_check_time

_code_check_time = code_check_time

if 1:

if not os.path.isfile(local_path):

f = open(local_path,'w+')

txt = """[local]

need_stop = 0

need_restart = 0"""

f.write(txt)

f.close()

con = ConfigParser()

con.read_file(codecs.open(local_path,'r+',"utf-8-sig"))

con.set('local','need_stop','0')

con.set('local','need_restart','0')

con.write(open(local_path,'w+'))

_f = True

while True:

con.read_file(codecs.open(local_path,'r+',"utf-8-sig"))

if not con.get('local','need_stop') == '1':

_res = os.popen('git pull').read()

if 'Fast-forward' in _res:

con.set('local','need_stop','1')

else:

con.set('local','need_stop','0')

con.write(open(local_path,'w+'))

if con.get('local','need_restart') == '1' or _f:

_f = False

p = Process(target=fun,args=args,kwargs=kwargs)

p.start()

con.set('local', 'need_restart','0')

con.write(open(local_path,'w+'))

time.sleep(10)

def check_stop_flag():

"""

检测是否应该停止,在被托管的进程里使用

"""

con = ConfigParser()

con.read_file(codecs.open(local_path,'r+','utf-8-sig'))

if con.get('local','need_stop') == "1":

print('code was updata,now stop running!!')

con.set('local','need_stop',"0")

con.set('local','need_restart',"1")

con.write(open(local_path,"w+"))

exit(0)

测试main.py文件

#-*-coding:utf-8-*-

from auto import check_stop_flag,auto_manager_main,set_code_check_time

import time

def run(x=0,y=0):

#开始子进程

print('run!!!!')

for i in range(x,500):

#设置在这里检测是否要退出进程

check_stop_flag()

#....做不应该突然中断任务....

time.sleep(1)

print('i={} y={}'.format(i,y))

#....做完了...

def tx(y=1):#(稍后测试我把1改成10)

#main函数【可变参数可以传这里,如果参数值改变,程序重启后会跟随改变】

run(x=1,y=y)#(稍后测试我把1改成10)

if __name__ == '__main__':

#设置检测频率(似乎并不会生效,待验证优化)

set_code_check_time(1)

#把进程委托自动管理【固定参数可以这里传入,重启程序参数也不会跟随改变的】

auto_manager_main(tx,y=1)#(稍后测试我把1改成10)

我先运行main.py文件,顺利的执行后,我在git上把参数x和y的值由1改成10。结果如下。

主进程PID: 6004

run!!!!

i=1 y=1

i=2 y=1

i=3 y=1

i=4 y=1

i=5 y=1

i=6 y=1

i=7 y=1

i=8 y=1

i=9 y=1

i=10 y=1

i=11 y=1

remote: Enumerating objects: 5, done.

remote: Counting objects: 100% (5/5), done.

remote: Compressing objects: 100% (3/3), done.

remote: Total 3 (delta 2), reused 0 (delta 0)

i=12 y=1g objects: 33% (1/3)

Unpacking objects: 100% (3/3), done.

From gitee.com:kid0/tx

3ca10d8..9f08a5d master -> origin/master

i=13 y=1

code was updata,now stop running!!

run!!!!

i=10 y=1

i=11 y=1

i=12 y=1

i=13 y=1

i=14 y=1

在我git改了代码后,main正常的自己退出,并且重启了。参数也是用最新的去运行。

实验完成!!!投入使用!

注意:

1、.gitignore文件必须加入忽略local.txt文件!!!否则会导致冲突,无法下拉代码!!!

2、可能会被修改的参数绝对不能由auto_manager_main传!应当用另一个函数简单包起main函数,像我测试的那样。

解疑:

1、为什么用Process(进程)而不是threading(线程)?

python虽然是解释性语言,但它需要把py编译成pyc文件去运行。进程启动时会重新编译,但线程不会。大家可以试试。虽然会更新代码并重启,但是运行结果不会改变。

2、是否适用于所有python项目?

适用于“一套代码放在多个客户机,并且经常更新git”的情况。对于server服务我并不推荐。因为server服务应该是累积一定的更新后再更新的线上。

3、直接杀掉进程用脚本启动会不会更简单?

条条大路通罗马。方法很多,看你喜欢。像我的项目,任务是从队列拿的。如果突然干掉了进程,任务就会丢失,而且我这每个任务都十分关键!条条任务都是钱!(我有双重保护,拿到任务会写到本地文件内,完成再删除,防一手机器宕机的可能)如果是普通爬虫之类的倒无所谓,丢失1-2条数据没关系的。

4、git pull为什么不是检测“Already up to date”?

一开始我也是这样的考虑的。但是,网络异常、冲突、sshkeygen失效等问题都会导致无限的重启程序。因此只能检测pull成功下拉的标识。

————————————————————————————————————————————————————————

以上就是我开发的模块和理解。欢迎大家使用和改进。

转载请注明出处。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值