无法从带有子进程的标准输出中获取结果 [英] Unable to get result from stdout with subprocess

查看:30
本文介绍了无法从带有子进程的标准输出中获取结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在发出命令后让结果显示在控制台中.

例如: H:/path/to/openssl.exe x509 -in H:/path/to/cert.pem -noout -subject

此命令在打开的 cmd.exe 中生成加密证书的值,但我无法获得与使用 subprocess 模块返回的变量相同的结果.

到目前为止我已经尝试过(其中 cmd 是上面的例子):

# 检查输出是否进入 stderrout = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)# 尝试使用 Popenout = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True).communicate()[0]# 尝试使用 Popen 不使用通信()p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)out = p.stdout.read()

所有的 print (out) 值都是 b''.

我什至将 cmd 分解为多个 args 用于 check_output()Popen() 这样它看起来像:["H:/path/to/openssl.exe", "x509 -in H:/path/to/cert.pem -noout -subject"].>

我确实有另一种方法来实现结果,但这需要运行包含以下命令的 .bat 文件:start cmd/k "... > H:/path/to/temp.txt" 其中 ... 是这里有问题的命令.这会将 .exe 输出重定向到一个临时文件(出于安全目的),我在将内容读入变量后将其删除.

支持信息:

如果运行命令的第一部分(.exe),它会打开该程序的自定义控制台.命令的其余部分在该控制台中执行,然后该控制台关闭.但是,如果在 cmd.exe 控制台中使用整个命令系列,则输出将显示在该控制台中.因此,为什么在我的 .bat 替代方法中使用 " " ,因为它将它作为一个完整的命令发布到打开的控制台.

使用 subprocess.Popen(["cmd.exe"])C:\Python36> 打开控制台,我可以发出有问题的命令并得到我想要的确切结果.不过,我似乎无法以 Python 方式抓取它.但是,subprocess.Popen(["cmd.exe", "H:/path/to/openssl.exe"]) 并没有执行第二条命令;打开控制台但不启动 .exe 控制台.

更新:

我能够得到结果,但我不喜欢我到达那里的方式.是否有更短的方法来执行以下操作:

p = subprocess.Popen("H:/path/to/openssl.exe", stdin=PIPE, stdout=PIPE)# b 用于字节类型要求p.stdin.write(b"x509 -in H:/path/to/cert.pem -noout -subject")p.stdin.close()out = p.stdout.read()

我还可以使用以下方法生成结果:

p = os.popen("start cmd/k H:/path/to/openssl.exe -in H:/path/to/cert.pem -noout -subject")

尝试将 .read() 添加到上面,但打印了一个空行

解决方案

您是否尝试将整个命令存储为原始字符串并使用 shell=True 传递它

cmd = r'H:/path/to/openssl.exe x509 -in H:/path/to/cert.pem -noout -subject'p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)out = p.communicate()打印(输出[0])#用于标准输出print(out[1]) # for std err

这对我的 stderr 有用,

打印 p.communicate()[1]

b'无法加载证书\r\n3636:error:0D07209B:asn1 编码例程:ASN1_get_object: 太长:./crypto/asn1/asn1_lib.c:142:\r\n3636:error:0D068066:asn1 zh编码例程:ASN1_CHECK_TLEN:坏对象头:./crypto/asn1/tasn_dec.c:1281:\r\n3636:错误:0D07803A:asn1 编码例程:ASN1_ITEM_EX_D2I:嵌套的 asn1 错误r:./crypto/asn1/tasn_dec.c:380:Type=X509\r\n3636:error:0906700D:PEM 例程:PEM_ASN1_read_bio:ASN1 lib:./crypto/pem/pem_oth.c:83:\r\n'

I need to get the result being displayed in the console after issuing a command.

e.g.: H:/path/to/openssl.exe x509 -in H:/path/to/cert.pem -noout -subject

This command produces values of an encrypted certificate when placed in an opened cmd.exe but I am unable to get the same result as a returned variable using the subprocess module.

So far I have attempted (where cmd is the e.g. above):

# checking if output is going to stderr
out = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
# attempt with Popen
out = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True).communicate()[0]
# attempt with Popen not using communicate()
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
out = p.stdout.read()

All the print (out) values are b''.

I have even broken the cmd into multiple args for both check_output() and Popen() such that it would look like: ["H:/path/to/openssl.exe", "x509 -in H:/path/to/cert.pem -noout -subject"].

I do have an alternative method to achieve the result, but that requires running a .bat file that contains the command: start cmd /k "... > H:/path/to/temp.txt" where the ... is the command in question here. This redirects the .exe output to a temp file (for security purposes) which I delete after reading contents into a variable.

Supporting information:

If the first part of the command is run (the .exe) it opens custom console for that program. The remainder of the command is executed in that console and then that console closes. However if the whole command series is used in a cmd.exe console, the output is displayed in that console. Hence why the use of " " in my alternate method of a .bat as it issues it to the open console as a whole command.

Use of subprocess.Popen(["cmd.exe"]) opens a console at C:\Python36> and I can issue the command in question and get the exact result I want. I cannot seem to grab it pythonically though. However, subprocess.Popen(["cmd.exe", "H:/path/to/openssl.exe"]) does not execute the second command; opens a console but does not start the .exe console.

Update:

I was able to get a result, but I don't like how I got there. Is there a shorter way to do the following:

p = subprocess.Popen("H:/path/to/openssl.exe", stdin=PIPE, stdout=PIPE)
# b for byte-type requirement
p.stdin.write(b"x509 -in H:/path/to/cert.pem -noout -subject")
p.stdin.close()
out = p.stdout.read()

I can also produce the result with:

p = os.popen("start cmd /k H:/path/to/openssl.exe -in H:/path/to/cert.pem -noout -subject")

Tried to add .read() to the above, but prints a blank line

解决方案

Have you tried storing the entire command as raw string and passing it with shell=True

cmd = r'H:/path/to/openssl.exe x509 -in H:/path/to/cert.pem -noout -subject' p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out = p.communicate() print(out[0]) #for std out print(out[1]) # for std err

Edit: This worked for me with stderr,

print p.communicate()[1]

b'unable to load certificate\r\n3636:error:0D07209B:asn1 encoding routines:ASN1_ get_object:too long:./crypto/asn1/asn1_lib.c:142:\r\n3636:error:0D068066:asn1 en coding routines:ASN1_CHECK_TLEN:bad object header:./crypto/asn1/tasn_dec.c:1281: \r\n3636:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 erro r:./crypto/asn1/tasn_dec.c:380:Type=X509\r\n3636:error:0906700D:PEM routines:PEM _ASN1_read_bio:ASN1 lib:./crypto/pem/pem_oth.c:83:\r\n'

这篇关于无法从带有子进程的标准输出中获取结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆