求解惑, Python 多进程问题

2020-01-09 21:09:27 +08:00
 alexlip

需求:多进程使用 mysqldump 分表逻辑备份 mysql.

开始使用 gnu parallel 来进行多进程备份,发现如果有一个进程备份时间久的话,会卡住已完成的进程等待这个进程. 不太了解 prarllel,所以考虑用 python multiprocessing.pool 来管理进程,目的是尽快的分配任务让多核来完成任务. if name == 'main': result = list() with open(sys.argv[1],'r') as o: lines = csv.reader(o) for line in lines: result.append(line) p = Pool(5) for i in result: p.apply_async(run,(i,)) p.close() p.join()

使用以上方式直接创建 pool,在 run 里使用 os.system 调用 mysqldump 执行备份工作.测试发现, 1234 进程已经完成备份,5 还未完成. 在这种情况下,1234 进程在等待 5 的完成, 并不是理想中的继续接任务执行.

求解惑,这是什么情况? 如何能实现我的需求. 如果用 queue 在 run 函数中读取队列,能否实现?

3024 次点击
所在节点    Python
16 条回复
ipwx
2020-01-09 21:12:15 +08:00
如果你只有五个任务,那么 1234 跑完等第 5 个不是很合适么。。。

你这需求都没有描述清楚,而且排版乱七八糟。
alexlip
2020-01-09 21:19:21 +08:00
@ipwx 不好意思. 发的时候是正常的[哭] ...
实际任务有 100 多, 开了 10 个进程.
所以我想问的是, 一批次执行 10 个任务的情况下, 是要等待 10 个任务完成,才会进行后续的任务吗?
wuwukai007
2020-01-09 21:19:54 +08:00
os.system 是阻塞的,就算开进程池也没用,5 个进程也在等待,用线程把 os.system 包起来
alexlip
2020-01-09 21:22:24 +08:00
@wuwukai007 我理解 os.system 是阻塞的, 我的想法是等 os.system("mysqldump") 执行完毕,再继续执行任务.
我的问题是 5 个 os.system 4 个已经完成, 并没有继续接受新的任务执行.而是在等待第 5 个执行结束
ipwx
2020-01-09 21:31:08 +08:00
你这就是你的全部代码么? 如果不是,请原样发上来。另外其实 thread 就能搞定不需要 process,毕竟你是调用了 os.system
alexlip
2020-01-09 21:35:12 +08:00
不知道怎么编辑追加帖子. 只能再回复里写了.

100 个需要执行的任务, 开 10 进程. 使用 Pool, 期望实现哪个进程空闲哪个进程执行任务.因为表有大小,执行时长不同.现在的情况是 123456789 执行完毕, 10 还在执行. 123456789 并没有继续接任务执行,而是在等待 10 的完成. 在 10 完成后才会接后面的 10 个任务同时开始执行. 我怎么才能实现 123456789 不等待 10, 直接继续后续任务?
ipwx
2020-01-09 21:38:05 +08:00
@alexlip 我说的是你的代码!代码!鬼知道你怎么写的代码出了你说的问题,我现在只能回答你,用 pool 可以不阻塞在第十个任务上
alexlip
2020-01-09 21:38:06 +08:00
```def run(dbtab):
folder='/home/www/dbbak/'+time.strftime("%Y%m%d",time.localtime())
cmd = "/home/www/mysql-5.7.12/bin/mysqlpump --host 127.0.0.1 -uwww --include-databases={0} --include-tables={1} --skip-watch-progress --compress-output=LZ4 > {2}/{0}/{1}.sql.lz4".format(dbtab[0],dbtab[1],folder)
os.system(cmd)

if __name__ == '__main__':
result = list()
with open(sys.argv[1],'r') as o:
lines = csv.reader(o)
for line in lines:
result.append(line)
p = Pool()
for i in result:
p.apply_async(run,(i,))
p.close()
p.join()
```
alexlip
2020-01-09 21:38:35 +08:00
@ipwx 代码很简单,已经贴上了,你帮忙看下?
wuwukai007
2020-01-09 21:45:35 +08:00
用线程池直接开 50 个,一样的
ipwx
2020-01-09 22:24:56 +08:00
@alexlip 我只能说你代码是对的。不信你可以把这段代码放到你自己机器上执行一下:

https://ideone.com/Ety65q
ipwx
2020-01-09 22:25:09 +08:00
至少 Python 层面的代码是没问题的。
ipwx
2020-01-09 22:35:30 +08:00
实在不行你手搓一个多线程试试呗,给你个 demo:

https://ideone.com/mK2PfL
alexlip
2020-01-09 22:50:51 +08:00
@ipwx 好的,谢谢. 我去测试个试试
leishi1313
2020-01-10 03:00:28 +08:00
更多像是 mysqldump 的问题而不是 python 的问题
aaronhua
2020-01-13 09:58:00 +08:00

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/636639

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX