[求助] subprocess 的 stdout 堵塞问题

2017-08-28 08:25:41 +08:00
 ouiki
要求是这样的:
1 ) 登入 mysql 服务器( mysql -h localhost -uroot -p1234 )。
2 ) 输入 mysql 内部命令 show databases,如果返回的内容出现 mysql (存在 mysql DB )就立刻强制退出整个 python 程序。
(关于要求 2 的解释,假如 show databases 的返回内容是 information_schema \r\n mysql \r\n test。不要等到 test 出现,马上就退出或者杀死该程序)

我认为只有用 subprocess 能够比较好的完成以上功能,所以以下都是以使用 subprocess 为前提。

个人试了好多方法,都不成功。
方法 1:把 stdout 放到线程里


def stdout_theard(p_stdout):
time.sleep(0.01)
for i in range(3000):
print p_stdout.readline()

s_command = 'mysql -h localhost -uroot -p1234'
sub_process = subprocess.Popen(command , stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True)
thread_read_output = threading.Thread(target=stdout_theard, args=(sub_process.stdout,))
thread_read_output.setDaemon('True')
thread_read_output.start()

sub_process.stdin.write('show databases;\r\n')

方法 2:把 stdout 重定向到文件里
s_command = 'mysql -h localhost -uroot -p1234'
f_out = tempfile.TemporaryFile(mode='w+')
f_err = tempfile.TemporaryFile(mode='w+')
sub_process = subprocess.Popen(command , stdin = subprocess.PIPE, stdout = f_out, stderr = f_err, shell = True)

或者:
os.dup2(sub_process.stdout.fileno(), f_out.fileno())

以上方法都没成功。
希望前辈高手们指点。

另,以上只是用 mysql 打了个比方,实际的环境不太好说。
必须得调用一个 exe ( cisco anyConnect ),得到返回值。但登陆这个 exe 的时候,一旦给定的用户名密码错误,它会一直用这组错误的用户名密码试,直到该用户被锁死。
退出的原因就是,在第一次用户名密码错误时,就退出,避免 exe 反复试,导致锁死。
6201 次点击
所在节点    Python
26 条回复
ouiki
2017-08-28 15:56:49 +08:00
@araraloren 谢谢,按你说的确实是有输出。赞啊~~

接下来就是我的问题了,我以为用 mysql,大家都有这个环境,就能很好的说明这个问题。看来大能果然不能糊弄。
我实际的问题和 mysql 类似,是叫“ cisco anyConnect ” 的一个程序( vpncli.exe )。
流程是差不多,通过 vpncli.exe 登录⇒建立 VPN 连接⇒返回状态⇒访问测试页面⇒退出 vpncli.exe 。
所以 mysql -n 参数我是学到了,但 vpncli.exe 没有-n 参数。
araraloren
2017-08-28 17:00:20 +08:00
@ouiki
那这个没有你说的那个选项的话不好说, 你可以考虑上面楼层说的伪终端
不过看你是 win 下,具体情况那就不清楚具体支持不支持 WIN 不了
不过还有一个办法就是你去和 cmd/shell 交互,而不是和你的应用程序交互。。
ouiki
2017-08-29 09:06:52 +08:00
@araraloren 再次感谢。
客户那边限制,只能使用 win。

>>> 不过还有一个办法就是你去和 cmd/shell 交互,而不是和你的应用程序交互
这是个思路。
ouiki
2017-08-29 09:07:27 +08:00
@guyskk 感谢,那篇文章让我受益良多。
lolizeppelin
2017-08-31 13:28:37 +08:00
不要用 readline 老老实实 read
lolizeppelin
2017-08-31 13:33:26 +08:00
还有 不要只顾 stdout 有些软件不标准
普通错误都往 stderr 里塞

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

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

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

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

© 2021 V2EX