在具有退出状态的单独变量中获取stderr和stdout

时间:2015-12-18 10:25:55

标签: python python-2.7

我必须为我的生产服务器编写一个Python代码,因此试图通过一个例子来清除我的概念。 Python脚本必须调用并执行bash shell脚本 - shell脚本可能会转储大量消息并成功退出或退出unisng exit(2)系统调用。因此我尝试通过以下方法:

import subprocess
try:
        output = subprocess.check_output(
                'bash mytest',
            shell=True,
            stderr=subprocess.STDOUT,
        )
        print 'Have %d bytes in output' % len(output)
        print output
except subprocess.CalledProcessError, e:
        print "Error String:", e.output
        print "Error Return code:", e.returncode

代码工作正常但是它是正确的调用方式,因为脚本可以打印数百行(使用echo)。

输出变量是否同时包含bash脚本打印的stderr和stdout消息?我可以在单独的变量中获取bash脚本的stderr和stdout消息 - 请记住,如果脚本成功运行,可能根本没有任何stderr消息吗?

我还应该假设,如果没有抛出异常subprocess.CalledProcessError,返回代码为0(SUCCESS)?

有没有更好的方法来实现相同的方法 - 这种方法会确保Python脚本会等到bash脚本完成吗?

提前致谢。

2 个答案:

答案 0 :(得分:1)

我也遇到了同样的问题,并通过POTCHIA从PMOTW链接中提出的建议解决了这个问题,为下面的简单示例提供了适用于我的解决方法:

import SwiftUI

struct WidthPreferenceKey: PreferenceKey {

    static var defaultValue: [CGFloat] = []
    static func reduce(value: inout [CGFloat], nextValue: () -> [CGFloat]) {
        value.append(contentsOf: nextValue())
    }

}

struct EqualWidth: ViewModifier {

    func body(content: Content) -> some View {
        content
            .overlay(
                GeometryReader { proxy in
                    Color.clear
                        .preference(
                            key: WidthPreferenceKey.self,
                            value: [proxy.size.width]
                        )
                }
            )
    }

}

extension View {
    func equalWidth() -> some View {
        modifier(EqualWidth())
    }
}

struct ContentView: View {

    @State private var width: CGFloat? = nil

    var body: some View {
        NavigationView {
            List {
                HStack {
                    Text("5.")
                        .equalWidth()
                        .frame(width: width, alignment: .leading)
                    Text("John Smith")
                }
                HStack {
                    Text("20.")
                        .equalWidth()
                        .frame(width: width, alignment: .leading)
                    Text("Jane Doe")
                }
            }
            .onPreferenceChange(WidthPreferenceKey.self) { widths in
                if let width = widths.max() {
                    self.width = width
                }
            }
            .listStyle(GroupedListStyle())
            .navigationBarTitle("Challenge")
        }
    }

}

答案 1 :(得分:0)

如果要同时捕获stdoutstderr,则必须使用较低级别的功能。扩展check_output的源代码,这是您可以做的:

process = Popen(stdout=PIPE, stderr=PIPE, *popenargs, **kwargs)
output, stderr = process.communicate()
retcode = process.poll()
if retcode:
    cmd = kwargs.get("args")
    if cmd is None:
        cmd = popenargs[0]
    raise CalledProcessError(retcode, cmd, output=stderr)  # or your own exception
return output