我必须为我的生产服务器编写一个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脚本完成吗?
提前致谢。
答案 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)
如果要同时捕获stdout
和stderr
,则必须使用较低级别的功能。扩展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