
1 21grams 2017-08-28 09:54:22 +08:00 via Android 没成功具体是什么问题? |
2 ouiki OP 放到线程里仍旧是阻塞。 重定向到文件里,写不进去。文件总是空,只有强制退出( Ctrl+C )后,才能写到文件里,看来也是阻塞的问题。 大牛,或者说有没有成功的经验。很可能我的写法也有问题。 |
3 araraloren 2017-08-28 10:12:18 +08:00 经过测试你需要 添加一个 -n 在 mysql 的命令行里 它默认开启了缓冲 |
4 araraloren 2017-08-28 10:13:59 +08:00 我用 Perl 6 来测试。。 my $p = Proc::Async.new(<mysql -n -P3306 -u ovirt -pdefault>, :w); $p.stdout.tap(&say); $p.stderr.tap(&say); my $pp = $p.start; await $p.put("show databases;\r\n"); say "WAITING OVER"; await $pp; 输出 Database information_schema mysql performance_schema |
5 topbandit 2017-08-28 10:27:40 +08:00 @ouiki linux pipe size 大小 512B*8= 4096Bytes,Pipe 满了就会阻塞。 处理方法 1 )即时取出 stdout,边读边写入文件,适用输出无穷大 2 ) Pipe.commucate(),读入内存,适用输出小的情况 |
6 ouiki OP 因为 python 的 subprocess 的 stdin,stdout 有阻塞的问题,所以我不会处理。 perl 没有阻塞的问题么?这到是个好消息,我可以用 perl 试试。 |
7 araraloren 2017-08-28 10:51:52 +08:00 @ouiki 你看了我说的话?我是说 mysql 默认开启了输出的缓冲,加上 -n 关掉估计就可以了。。 |
8 ouiki OP @araraloren 谢谢回复,学到了。 |
9 ouiki OP @topbandit 所谓“及时取出 stdout,边读边写”,的意思是 p.stdout.flush() 么? 好像抓到点什么了? |
10 ouiki OP @topbandit stdout,stderr = Pipe.commucate() 是不是等到进程结束才输出?这个在我的程序里不适用。不能等到结束,还要有后续的动作。(事实上是用 cisco anyConnect 建立连接之后,测试上网) |
11 topbandit 2017-08-28 11:12:40 +08:00 @ouiki 边读边写: while 1: line = p.stdout.readline() write(line) 前边没仔细看你的需求,如果仅仅是 show databases 的输出,output 多大,会引起 pipe 阻塞? |
12 topbandit 2017-08-28 11:14:50 +08:00 前面多余,你用一条 mysql 命令搞好了 |
13 topbandit 2017-08-28 11:18:44 +08:00 mysql -u -p -e 此帖终结 |
14 guyskk 2017-08-28 13:11:14 +08:00 via Android 缓冲 IO 的问题。PIPE 和普通文件默认都是全缓冲的,缓冲区没满就不会进行实际 IO,所以读不到数据。 两个办法: 1. mysql 加参数,让它强制冲洗缓冲区 2. 使用伪终端(pty),它默认是行缓冲的 分享篇博客 深入理解子进程 : http://www.kkblog.me/notes/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3%E5%AD%90%E8%BF%9B%E7%A8%8B |
15 ouiki OP @topbandit 大神留步。 我改了一下我的代码。试了,不打印。求大神给看看。 def stdout_theard(stdout_lock, p_stdout): for i in range(3000): s = p_stdout.readline() if len(s)>0: print s # 这里没有打印 time.sleep(0.01) if __name__ == "__main__": os.chdir('C:\\Program Files (x86)\\MySQL\\MySQL Server 5.0\\bin') s_mian_command = 'mysql -h localhost -uroot -p1234' l_command = ['show databases;', 'use mysql;', 'show tables;'] sub_process = subprocess.Popen(s_mian_command, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True) stdout_lock = threading.Lock() thread_read_output = threading.Thread(target=stdout_theard, args=(stdout_lock,sub_process.stdout)) thread_read_output.setDaemon('True') thread_read_output.start() for s_command in l_command: time.sleep(1) sub_process.stdin.write(s_command + '\r\n') print s_command # 这里是打印的 打印的结果就是: show databases; use mysql; show tables; 密码啥的都没问题。后台也确实实执行了的(我用 PowerCmd 能看到后台是执行了的),就是没打印。 黑人问号黑人问号。 |
16 llbgurs 2017-08-28 15:07:54 +08:00 为什么没有 sub_process.p.communicate() |
17 ouiki OP 感谢大家一直在帮助我,怎奈我天资有限,一直没有解决。 @llbgurs out,err = sub_process.communicate()的意思是线程结束后才返回 stdout 和 stderr 吧? 我的程序不能停止后才返回,还有后续的动作。 |
18 araraloren 2017-08-28 15:39:15 +08:00 @ouiki ...真是不可救药了,我都说了是 mysql 的问题,跟你的用法没有关系。。 这就如同 程序本身没有输出 你还能 capture 到输出? |
19 topbandit 2017-08-28 15:42:32 +08:00 这里排版不太好,我在 OSC 写了段 https://my.oschina.net/u/3573498/blog/1524999 |
20 llbgurs 2017-08-28 15:45:39 +08:00 @ouiki mysql 不能这样执行吗? mysql -h localhost -uroot -p1234 -e "show databases" |
21 ouiki OP @araraloren 谢谢,按你说的确实是有输出。赞啊~~ 接下来就是我的问题了,我以为用 mysql,大家都有这个环境,就能很好的说明这个问题。看来大能果然不能糊弄。 我实际的问题和 mysql 类似,是叫“ cisco anyConnect ” 的一个程序( vpncli.exe )。 流程是差不多,通过 vpncli.exe 登录建立 VPN 连接返回状态访问测试页面退出 vpncli.exe 。 所以 mysql -n 参数我是学到了,但 vpncli.exe 没有-n 参数。 |
22 araraloren 2017-08-28 17:00:20 +08:00 @ouiki 那这个没有你说的那个选项的话不好说, 你可以考虑上面楼层说的伪终端 不过看你是 win 下,具体情况那就不清楚具体支持不支持 WIN 不了 不过还有一个办法就是你去和 cmd/shell 交互而不是和你的应用程序交互。。 |
23 ouiki OP |
25 lolizeppelin 2017-08-31 13:28:37 +08:00 via Android 不要用 readline 老老实实 read |
26 lolizeppelin 2017-08-31 13:33:26 +08:00 via Android 还有 不要只顾 stdout 有些软件不标准 普通错误都往 stderr 里塞 |