Swift:使用管道缓冲'Process'的很长参数

Swift:使用管道缓冲'Process'的很长参数,swift,nspipe,Swift,Nspipe,问题 我试图从Swift可执行文件调用Python函数 在参数变得太长并且我开始出现错误之前,这一切都非常有效: 未捕获异常n内部一致性异常 原因:“无法生成posix_:错误7” 这本质上意味着我发送python代码进行处理的数据(我的参数)太长 最后的选择 最明显的解决方案是将数据写入文件,并向脚本发送包含数据的文件的路径。这带来了明显的性能限制 可能更好的选择 这就是我需要帮助的地方:我认为可能可以缓冲这些数据,而不是在一块中发送所有数据 我试着用许多不同的关键字组合来研究这个问题,在过去

问题

我试图从Swift可执行文件调用Python函数

在参数变得太长并且我开始出现错误之前,这一切都非常有效:

未捕获异常
n内部一致性异常

原因:“无法生成posix_:错误7”

这本质上意味着我发送python代码进行处理的数据(我的参数)太长

最后的选择

最明显的解决方案是将数据写入文件,并向脚本发送包含数据的文件的路径。这带来了明显的性能限制

可能更好的选择

这就是我需要帮助的地方:我认为可能可以缓冲这些数据,而不是在一块中发送所有数据

我试着用许多不同的关键字组合来研究这个问题,在过去的一天里,我在网上读了很多文章,但没有人回答我的问题:是否可以使用
进程
es和
管道
来缓冲数据以绕过内核
ARG_MAX
限制260000字节左右

代码

因为查看我当前用于调用Python函数的代码总是有帮助的,所以我有:

@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 {}
过了一会儿:

//
//  Call classifier on data
//
let pyStcriptPath = "\(Bundle.main.bundlePath)/Classification/****Classify.py"

//
// The fonction I'm calling here, 'shell', is the one defined just above in my question
//
let pyResult = shell("python", pyStcriptPath, "\(featureVector)", "\(signalType)")

您可以使用管道将大负载发送到脚本的标准输入。当然,假设只有一个参数导致您的问题(即,您仍然可以使用常规命令行参数继续发送的所有其他参数)

例如:

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)