actix Actor怎么会有PyO3Python?
How can actix Actor have PyO3 Python?
我正在尝试创建具有 PyO3 Python 解释器和 Py 对象的 Actix Actor。
问题是创建 python 解释器 actor 的正确方法是什么?
我认为错误是由静态定义的 Actor 特征引起的。
https://docs.rs/actix/0.7.4/actix/trait.Actor.html
Actor或者Context有没有object需要life参数的方式?
rust 版本:nightly-2018-09-04,actix 版本:0.7.4
这是当前代码。
extern crate actix;
extern crate actix_web;
extern crate pyo3;
use actix::prelude::*;
use actix_web::{http, server, ws, App, HttpRequest, HttpResponse, Error};
use pyo3::{Python, GILGuard, PyList};
struct WsActor<'a> {
// addr: Addr<PyActor>,
gil: GILGuard,
python: Python<'a>,
pylist: &'a PyList,
}
impl<'a> Actor for WsActor<'a> {
type Context = ws::WebsocketContext<Self>;
}
fn attach_ws_actor(req: &HttpRequest<()>) -> Result<HttpResponse, Error> {
let gil = Python::acquire_gil();
let python = gil.python();
let pylist = PyList::empty(python);
let actor = WsActor {gil, python, pylist};
ws::start(req, actor)
}
fn main() {
let sys = actix::System::new("example");
server::new(move || {
App::new()
.resource("/ws/", |r| r.method(http::Method::GET).f(attach_ws_actor))
}).bind("0.0.0.0:9999")
.unwrap()
.start();
}
此代码无法编译并出现此错误。
error[E0478]: lifetime bound not satisfied
--> src/main.rs:15:10
|
15 | impl<'a> Actor for WsActor<'a> {
| ^^^^^
|
note: lifetime parameter instantiated with the lifetime 'a as defined on the impl at 15:6
--> src/main.rs:15:6
|
15 | impl<'a> Actor for WsActor<'a> {
| ^^
= note: but lifetime parameter must outlive the static lifetime
Actor trait的定义是
pub trait Actor: Sized + 'static { ... }
这意味着,你的一生 'a
必须是 'static
。
这里有点example:
use std::marker::PhantomData;
trait Foo: Sized + 'static {
fn foo();
}
struct Bar<'a> {
_marker: PhantomData<&'a i32>,
}
impl<'a> Foo for Bar<'a> { //not possible
fn foo() {}
}
struct Baz<'a> {
_marker: PhantomData<&'a i32>,
}
impl Foo for Baz<'static> { //possible
fn foo() {}
}
正如所说,您可以在WsActor
中存储Py<PyList>
对象。
要恢复 PyList
,您可以再次获取 GIL 并调用 AsPyRef
特征(Py<T>
实现)的 .as_ref(python)
方法。
举例如下:
extern crate actix;
extern crate actix_web;
extern crate pyo3;
use actix::prelude::*;
use actix_web::{http, server, ws, App, HttpRequest, HttpResponse, Error};
use pyo3::{Python, PyList, Py, AsPyRef};
struct WsActor {
// addr: Addr<PyActor>,
pylist: Py<PyList>,
}
impl Actor for WsActor {
type Context = ws::WebsocketContext<Self>;
}
impl StreamHandler<ws::Message, ws::ProtocolError> for WsActor {
fn handle(&mut self, _: ws::Message, _: &mut Self::Context) {
let gil = Python::acquire_gil();
let python = gil.python();
let list = self.pylist.as_ref(python);
println!("{}", list.len());
}
}
fn attach_ws_actor(req: &HttpRequest<()>) -> Result<HttpResponse, Error> {
let gil = Python::acquire_gil();
let python = gil.python();
let pylist = PyList::empty(python);
let actor = WsActor {
pylist: pylist.into()
};
ws::start(req, actor)
}
fn main() {
let sys = actix::System::new("example");
server::new(move || {
App::new()
.resource("/ws/", |r| r.method(http::Method::GET).f(attach_ws_actor))
}).bind("0.0.0.0:9999")
.unwrap()
.start();
}
我正在尝试创建具有 PyO3 Python 解释器和 Py 对象的 Actix Actor。
问题是创建 python 解释器 actor 的正确方法是什么?
我认为错误是由静态定义的 Actor 特征引起的。 https://docs.rs/actix/0.7.4/actix/trait.Actor.html
Actor或者Context有没有object需要life参数的方式?
rust 版本:nightly-2018-09-04,actix 版本:0.7.4
这是当前代码。
extern crate actix;
extern crate actix_web;
extern crate pyo3;
use actix::prelude::*;
use actix_web::{http, server, ws, App, HttpRequest, HttpResponse, Error};
use pyo3::{Python, GILGuard, PyList};
struct WsActor<'a> {
// addr: Addr<PyActor>,
gil: GILGuard,
python: Python<'a>,
pylist: &'a PyList,
}
impl<'a> Actor for WsActor<'a> {
type Context = ws::WebsocketContext<Self>;
}
fn attach_ws_actor(req: &HttpRequest<()>) -> Result<HttpResponse, Error> {
let gil = Python::acquire_gil();
let python = gil.python();
let pylist = PyList::empty(python);
let actor = WsActor {gil, python, pylist};
ws::start(req, actor)
}
fn main() {
let sys = actix::System::new("example");
server::new(move || {
App::new()
.resource("/ws/", |r| r.method(http::Method::GET).f(attach_ws_actor))
}).bind("0.0.0.0:9999")
.unwrap()
.start();
}
此代码无法编译并出现此错误。
error[E0478]: lifetime bound not satisfied
--> src/main.rs:15:10
|
15 | impl<'a> Actor for WsActor<'a> {
| ^^^^^
|
note: lifetime parameter instantiated with the lifetime 'a as defined on the impl at 15:6
--> src/main.rs:15:6
|
15 | impl<'a> Actor for WsActor<'a> {
| ^^
= note: but lifetime parameter must outlive the static lifetime
Actor trait的定义是
pub trait Actor: Sized + 'static { ... }
这意味着,你的一生 'a
必须是 'static
。
这里有点example:
use std::marker::PhantomData;
trait Foo: Sized + 'static {
fn foo();
}
struct Bar<'a> {
_marker: PhantomData<&'a i32>,
}
impl<'a> Foo for Bar<'a> { //not possible
fn foo() {}
}
struct Baz<'a> {
_marker: PhantomData<&'a i32>,
}
impl Foo for Baz<'static> { //possible
fn foo() {}
}
正如WsActor
中存储Py<PyList>
对象。
要恢复 PyList
,您可以再次获取 GIL 并调用 AsPyRef
特征(Py<T>
实现)的 .as_ref(python)
方法。
举例如下:
extern crate actix;
extern crate actix_web;
extern crate pyo3;
use actix::prelude::*;
use actix_web::{http, server, ws, App, HttpRequest, HttpResponse, Error};
use pyo3::{Python, PyList, Py, AsPyRef};
struct WsActor {
// addr: Addr<PyActor>,
pylist: Py<PyList>,
}
impl Actor for WsActor {
type Context = ws::WebsocketContext<Self>;
}
impl StreamHandler<ws::Message, ws::ProtocolError> for WsActor {
fn handle(&mut self, _: ws::Message, _: &mut Self::Context) {
let gil = Python::acquire_gil();
let python = gil.python();
let list = self.pylist.as_ref(python);
println!("{}", list.len());
}
}
fn attach_ws_actor(req: &HttpRequest<()>) -> Result<HttpResponse, Error> {
let gil = Python::acquire_gil();
let python = gil.python();
let pylist = PyList::empty(python);
let actor = WsActor {
pylist: pylist.into()
};
ws::start(req, actor)
}
fn main() {
let sys = actix::System::new("example");
server::new(move || {
App::new()
.resource("/ws/", |r| r.method(http::Method::GET).f(attach_ws_actor))
}).bind("0.0.0.0:9999")
.unwrap()
.start();
}