问题
我正试图从我的Swift可执行文件中调用Python函数。
这很有效,直到参数变得太长并且我开始收到错误为止:
未捕获的异常
NSInternalInconsistencyException
原因:“无法posix_spawn:错误7”
从本质上讲,这意味着我正在发送用于处理的python代码(我的参数)的数据太长。
最后的选择
最明显的解决方案是将数据写入文件,然后向脚本发送包含该数据的文件路径。这会带来明显的性能限制。
一个可能更好的选择
这是我需要的帮助:我认为可能缓冲这些数据,而不是全部发送一个数据块。
我尝试用多种不同的关键字组合进行研究,并且过去一天一直在线阅读许多文章,但没有一个回答我的问题:是否可以缓冲数据以避开内核强加{{1 }}使用ARG_MAX
和Process
限制大约260000字节?
代码
因为它总是可以帮助我查看当前用于调用Python函数的代码,这就是我所拥有的:
Pipe
再过一会儿:
@discardableResult
public static func shell(_ args: String...) -> String {
let task = Process()
task.launchPath = "/usr/bin/env"
task.arguments = args
let pipe = Pipe()
task.standardOutput = pipe
task.launch()
task.waitUntilExit()
// return task.terminationStatus
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output: String = String(data: data, encoding: String.Encoding.utf8)!
return output
}
// public static func shell(_ args: String...) -> String {}
答案 0 :(得分:0)
您可以使用 pipe 将大型有效负载发送到脚本的标准输入。当然,假设只有一个单个参数引起了您的问题(即,您仍然可以使用常规命令行参数继续发送的所有其他信息)。
例如:
func shell(stdin input: String, _ args: String...) -> String {
let task = Process()
task.launchPath = "/usr/bin/env"
task.arguments = args
let inPipe = Pipe()
task.standardInput = inPipe
inPipe.fileHandleForWriting.write(input.data(using: .utf8)!)
inPipe.fileHandleForWriting.closeFile()
let outPipe = Pipe()
task.standardOutput = outPipe
task.launch()
task.waitUntilExit()
let data = outPipe.fileHandleForReading.readDataToEndOfFile()
let output = String(data: data, encoding: .utf8)!
return output
}
快速测试:
func bigString() -> String {
var str = ""
for i in 0..<50_000 {
str.append("\(i % 10)")
}
return str
}
let script = "/PATH/TO/SCRIPT/echo.py"
let input = bigString()
let result = shell(stdin: input, "python", script, "some arg")
print(result)
打印:
ARG:ABC
STDIN:012345678901234567890123 ...
echo.py
脚本仅是:
import sys
print "ARG:", sys.argv[1]
print "STDIN:", sys.stdin.read()