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 1
@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 1
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 里塞 |