I'm trying to use async/await with processes in Rust. I'm using tokio
and tokio-process
:
#![feature(await_macro, async_await, futures_api)]
extern crate tokio;
extern crate tokio_process;
use std::process::Command;
use tokio_process::CommandExt;
fn main() {
tokio::run_async(main_async());
}
async fn main_async() {
let out = Command::new("echo")
.arg("hello")
.arg("world")
.output_async();
let s = await!(out);
}
Here is the error that I get:
error[E0277]: the trait bound `tokio_process::OutputAsync: std::future::Future` is not satisfied
--> src/main.rs:21:13
|
21 | let s = await!(out);
| ^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `tokio_process::OutputAsync`
|
= note: required by `std::future::poll_with_tls_waker`
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error[E0277]: the trait bound `tokio_process::OutputAsync: std::future::Future` is not satisfied
--> src/main.rs:21:13
|
21 | let s = await!(out);
| ^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `tokio_process::OutputAsync`
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
How do I get this right?
Tokio 0.1 and related crates are implemented using the stable futures 0.1 crate. The Future
trait from this crate is conceptually similar to the version of the Future
trait from the standard library but substantially different in details. async
/ await
syntax is built around the version of the trait in the standard library.
The not-yet-released Tokio 0.2 and related crates are implemented using the standard library Future
and are being reworked to better support async
/ await
syntax.
Tokio 0.2
[dependencies]
tokio = "0.2.0-alpha.2"
tokio-process = "0.3.0-alpha.2"
use tokio_process::Command;
#[tokio::main]
async fn main() -> std::io::Result<()> {
let out = Command::new("echo")
.arg("hello")
.arg("world")
.output()
.await?;
let s = String::from_utf8_lossy(&out.stdout);
println!("{}", s);
Ok(())
}
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.05s
Running `target/debug/tt`
hello world
Tested with:
- Rustc 1.39.0-nightly (6ef275e6c 2019-09-24)
Tokio 0.1
Performing an internet search for "tokio async await" leads to the aptly-named crate tokio-async-await. This documents how to enable Tokio to participate in the unstable futures:
[dependencies]
tokio = { version = "0.1.15", features = ["async-await-preview"] }
tokio-process = "0.2.3"
In your code, you have to translate between a Future
implemented against the trait from the futures 0.1 crate and from the standard library. An easy way to do this is to use the Tokio version of the await
macro:
#![feature(await_macro, async_await, futures_api)]
use std::process::Command;
use tokio_process::CommandExt;
fn main() {
tokio::run_async(main_async());
}
async fn main_async() {
let out = Command::new("echo")
.arg("hello")
.arg("world")
.output_async();
let s = tokio::await!(out);
println!("{:?}", s);
}
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.10s
Running `target/debug/oo`
Ok(Output { status: ExitStatus(ExitStatus(0)), stdout: "hello world\n", stderr: "" })
Tested with:
- Rust 1.34.0-nightly (e1c6d0057 2019-02-22)
- Rust 1.34.0-nightly (aadbc459b 2019-02-23)
See also:
来源:https://stackoverflow.com/questions/54853917/how-do-i-use-async-await-syntax-with-tokio