【问题标题】:Get output of subprocess without garbage获取没有垃圾的子进程的输出
【发布时间】:2017-11-27 09:37:14
【问题描述】:

Transcrypt Python to JavaScript 编译器中, 我使用以下代码通过子进程管道数据:

                process = subprocess.Popen (
                    [node.args [1] .s],
                    shell = True,
                    stdin = subprocess.PIPE,
                    stdout = subprocess.PIPE
                )
                process.stdin.write (sourceCode.encode ('utf8'))
                process.stdin.close ()
                while process.returncode is None:
                    process.poll ()
                targetCode = process.stdout.read (). decode ('utf8'). replace ('\r\n', '\n')

我的子进程是一个 Windows .bat 文件,其中包含:

python capitalize.py

capitalize.py的内容是:

import sys
content = sys.stdin.read ()
sys.stdout.write (content.upper ())

如果变量sourceCode最初包含:

dit
is
een
test

结果变量targetCode 将包含:

    D:\activ_tosh\geatec\transcrypt\qquick\Transcrypt\transcrypt\development\experiments\pipe>python capitalize.py 

    D:\activ_tosh\geatec\transcrypt\qquick\Transcrypt\transcrypt\development\experiments\pipe>call D:\python36_anaconda\python.exe capitalize.py 

        DIT
        IS
        EEN
        TEST

换句话说,命令的回显会添加到标准输出之前,正如预期的那样。

如果我以echo off 启动命令文件,则会得到回显,因此无济于事。

如何更改 subprocess.Popen 的代码(或围绕它的代码),使targetCode 仅包含:

        DIT
        IS
        EEN
        TEST

我已经尝试了很多东西,包括在各个地方使用echo off 和重新分配标准输出。而且我一直在谷歌上搜索很多,但没有找到解决方案。有谁知道如何解决这个问题?

[编辑1] @Mahesh Karia

我试过了:

                process = subprocess.Popen (
                    [node.args [1] .s],
                    shell = True,
                    stdout = subprocess.PIPE
                )
                print (111)
                targetCode = process.communicate (io.StringIO (sourceCode))[0]
                print (222)

这在打印 111 后挂起。

[编辑1]

我通过使用可执行文件(从 C++ 翻译)而不是 .bat 或 .py 文件作为过滤器解决了我的问题。这不会产生任何控制台回声。

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

int main () {
    string buffer;
    getline (cin, buffer, '\f');
    transform (buffer.begin(), buffer.end(), buffer.begin(), ::toupper);
    cout << buffer;
}

输入数据必须以终止字符结尾,在本例中我使用了 '\f':

'''
<div id="StudentContainer">
    {self.props.students.map((s) => (
        <StudentTile student={s}  key={s.searchval}  />
    ))}
</div>
\f'''

【问题讨论】:

  • 你试过subprocess.check_output()而不是Popen吗?
  • 不,我没有。在这种情况下,如何通过管道输入变量 sourceCode 的内容?
  • 你确定子进程模块被 Transcript 正确处理了吗? AFAIK,Transcrypt 旨在将 Python 源代码转换为 JavaScript,以便在浏览器中执行。你到底想达到什么目的?
  • 代码不依赖于 Transcrypt。如果它是独立代码,也会发生同样的问题。我想要实现的是启动一个子进程,向它发送一个字符串,让子进程将字符串转换为其他内容,然后将结果分配给一个变量。为了防止误解,我没有使用 Transcrypt 本身来编译这段代码,该代码是 Transcrypt 的增强,以允许外部源处理,例如JSX 的。
  • @JacquesdeHooge 像这样:x = check_output('echo "4*25"', shell=True).decode().strip()print(x)y = check_output(f'echo "{x}" | bc', shell=True).decode().strip()print(y)

标签: python subprocess transcrypt


【解决方案1】:

一种方法是使用communicate() 来获取输出。

processes = [Popen(cmd, shell=True, stdout=subprocess.PIPE) for cmd in self.cmd_list]
for p in processes: p.wait()
for p in processes:
    output = p.communicate()[0]
    print output

【讨论】:

  • 我已尝试相应地调整我的代码(请参阅 [EDIT1]),但现在它挂起。看来还是有问题。
  • 基本没挂,p.wait()等待进程完成执行。我需要事情以同步方式工作,这就是我使用 wait() 的原因,但如果你想遵循异步方式,那么你可以删除 p.wait(),我相信它会为你工作而不会挂起。
  • 我现在删除了process.wait (),但它仍然挂起。
  • 挂了,你能解释一下吗
  • 打印 111 然后停止,所以不会终止