一个简单的 Swift 封装,用于处理 Process,支持 Swift 并发和从 stdout 和 stderr 流式输出。
macOS 10.15 及以上
通过 Xcode (File > Add Packages...) 或将 Coquille 添加到项目的 Package.swift 文件中,将 Coquille 添加到你的项目中
dependencies: [
.package(url: "https://github.com/alexrozanski/Coquille.git", from: "0.3.0")
]
Coquille 公开了自己的 Process 类,你可以使用它来执行命令。Process.run() 是一个 async 函数,所以你可以直接 await 退出码
import Coquille
let process = Process(commandString: "pwd"))
_ = try await process.run() // Prints `pwd` to `stdout`
// Use `command:` for more easily working with variable command-line arguments
let deps = ["numpy", "torch"]
let process = Process(command: .init("python3", arguments: ["-m", "pip", "install"] + deps)))
_ = try await process.run()
默认情况下,Process 不会将产生的进程的任何输出管道到 stdout 和 stderr。 这可以通过 printStdout 和 printStderr 进行配置
import Coquille
let process = Process(commandString: "brew install wget", printStdout: true))
_ = try await process.run() // Pipes standard output to `stdout` but will not pipe error output to `stderr`
你也可以为 stdout 和 stderr 传递一个 OutputHandler,它将流式传输来自两者的内容
import Coquille
let process = Process(
commandString: "swift build",
stdout: { stdout in
...
},
stderr: { stderr in
...
})
_ = try await process.run() // Streams standard and error output to the handlers provided to `stdout:` and `stderr:`
// `isSuccess` can be used to test the exit code for success
let hasRuby = (try await Process(commandString: "which ruby").run()).isSuccess
// Use `errorCode` to get a nonzero exit code
if let errorCode = (try await Process(commandString: "swift build").run()).errorCode {
switch errorCode {
case 127:
// Command not found
default:
...
}
}
主要的 Process.run() 函数签名是
public func run() async throws -> Status
它允许你使用 Swift 并发来执行子进程并 await 退出状态。 但是,如果你想支持取消,你可以使用另一个 run() 函数
public func run(with completionHandler: @escaping ((Status) -> Void)) -> ProcessCancellationHandle
它立即返回一个不透明的 ProcessCancellationHandle 类型,你可以调用它的 cancel() 方法来取消执行,进程状态通过 completionHandler 闭包传递。
感谢 Ben Chatelain 撰写的关于拦截 stdout 的 博客文章,该文章用于实现测试套件中的一些测试。