【问题标题】:How do I use async/await syntax with Tokio?如何在 Tokio 中使用 async/await 语法?
【发布时间】:2019-02-24 16:20:44
【问题描述】:

我正在尝试将 async/await 与 Rust 中的进程一起使用。我正在使用tokio 和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);
}

这是我得到的错误:

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)

我怎样才能做到这一点?

【问题讨论】:

    标签: async-await rust rust-tokio


    【解决方案1】:

    TL;DR:使用 Tokio 0.2 或更高版本,它应该可以正常工作。

    Tokio 0.1 和相关的 crate 是使用 futures 0.1 crate 实现的。此 crate 中的 Future 特征在概念上类似于标准库中的 Future 特征版本,但在细节上有很大不同。 async / await 语法是围绕标准库中的 trait 版本构建的。

    Tokio 0.2 和相关 crates 使用标准库 Future 实现,并经过重新设计以更好地支持 async / await 语法。

    东京 0.2

    [dependencies]
    tokio = { version = "0.2", features = ["full"] }
    
    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/tokio2`
    hello world
    

    测试:

    • Rustc 1.39.0

    东京 0.1

    你必须translate between a Future implemented against the trait from the futures 0.1 crate and from the standard library。此外,您需要启动 Tokio 运行时服务,理想情况下适用于 Tokio 0.1 和 Tokio 0.3。这就是tokio-compat 的用武之地:

    [dependencies]
    futures = { version = "0.3", features = ["compat"] }
    tokio-compat = "0.1"
    tokio-process = "0.2"
    
    use futures::compat::Future01CompatExt;
    use std::process::Command;
    use tokio_process::CommandExt;
    
    fn main() {
        tokio_compat::run_std(main_async());
    }
    
    async fn main_async() {
        let out = Command::new("echo")
            .arg("hello")
            .arg("world")
            .output_async();
    
        // Convert future from 0.1 to 0.3
        let s = out.compat().await;
    
        println!("{:?}", s);
    }
    
    % cargo run
        Finished dev [unoptimized + debuginfo] target(s) in 0.07s
         Running `target/debug/tt`
    Ok(Output { status: ExitStatus(ExitStatus(0)), stdout: "hello world\n", stderr: "" })
    

    用 Rust 1.43.0 测试

    另见:

    【讨论】:

    • 当我使用 tokio v0.1.22 reqwest v0.10.0-alpha.2 tokio::run({ async fn reqwest::get(url).await got Error(Connect, Custom { kind: Other ,错误:“没有当前反应堆”})
    • @CSQGB reqwest alpha requires tokio alpha.
    • Tokio 0.1 与 reqwest alpha 不兼容,除非我使用 tokio v0.2.0-alpha ,对吧?
    • 你好 Shepmaster。 tokio-process 0.3.0-alpha.2 is in compatible with reqwest 0.10.0-alpha.2 I got error: failed to select a version for futures-core-preview.
    猜你喜欢
    • 2019-06-13
    • 1970-01-01
    • 1970-01-01
    • 2018-05-09
    • 2020-08-19
    • 1970-01-01
    • 2021-01-23
    • 2019-07-20
    • 2021-10-10
    相关资源
    最近更新 更多