【问题标题】:Passing json data from python to rust via pickle (or other)通过pickle(或其他)将json数据从python传递到rust
【发布时间】:2020-01-01 13:43:07
【问题描述】:

我正在尝试创建一个通用接口,以便能够使用来自 python(https://github.com/ProjitB/Rust-Libraries-to-Python) 的 rust 库。现在,虽然我有一个工作版本,但我在传递数据的过程中创建了一个临时文件,我想避免这种情况。关于如何做到这一点的任何想法?

所以我要做的是在 rust 中编写一个接口函数,它调用了我想从 python 中使用的 rust 库函数。为了从 python 传递参数,我通过 pickle 将其写入临时文件,并通过 serde_pickle 读取 rust 端的 args。

我坚持的是,虽然我能够将字符串从 python 传递给 rust(例如,文件名本身现在作为字符串传递),但当我无法使用 pickle 序列化数据时.也许是因为空字节?

# Rust Function Interface Definitions
ffi = FFI()
ffi.cdef("""
   typedef struct {int length; const char* response;} RetStruct;
   RetStruct rust_post(const char*);

""") 
LIB = ffi.dlopen("target/release/librequest_export.dylib")

def function_call(function, data):
    inp_file = tempfile.NamedTemporaryFile()
    with open(inp_file.name, 'wb') as handle:
        pickle.dump(data, handle, protocol=pickle.HIGHEST_PROTOCOL)
    val = function(to_string(inp_file.name))
    obj = pickle.loads(read_pickle_bytes(val.response, val.length))
    return obj['response']

def test_function_call():
    data = {'url': 'https://postman-echo.com/post', 'data': {"hello": "world"}}
    output = eval(function_call(LIB.rust_post, data))
    print(type(output))
    print(output)
    print(output["args"])

test_function_call()
use reqwest;
use url::Url;
use std::os::raw::c_char;
use std::ffi::CStr;
use serde_json as json;
use serde_pickle as pickle;
use std::collections::BTreeMap;
use std::fs;
use std::fs::File;
use std::io::{Read};
use std::mem;

#[repr(C)]
pub struct RetStruct {
    length: i64,
    response: *mut u8
}

pub extern "C" fn rust_post(input_temp_file: *const c_char) -> RetStruct{
    // File to read and write to
    let input_filename = unsafe { CStr::from_ptr(input_temp_file).to_str().expect("Not a valid UTF-8 string") };

    //Processing
    let reader: Box<Read> = Box::new(File::open(input_filename).unwrap());
    let decoded: json::Value = pickle::from_reader(reader).unwrap();
    let mut map = BTreeMap::new();

    //To Implement
    let data = &decoded["data"];
    let url = Url::parse(&decoded["url"].as_str().expect("Not a valid UTF-8 string")).unwrap();
    let client = reqwest::Client::new();
    let mut resp = client.post(url)
        .json(&data)
        .send().unwrap();
    map.insert("response".to_string(), resp.text().unwrap());

    //Processing
    let mut serialized = serde_pickle::to_vec(&map, true).unwrap();
    let x = serialized.len();
    let p = serialized.as_mut_ptr();
    mem::forget(serialized);
    RetStruct{
    length: x as i64,
    response: p
    }
}

代码显示了我当前如何在 python 和 rust 之间传递数据。如果我尝试以发送文件名的方式发送序列化的泡菜数据,我将无法恢复所有数据。

【问题讨论】:

    标签: python rust python-cffi


    【解决方案1】:

    序列化为 json 总是一个好主意。

    print({'url': 'https://postman-echo.com/post', 'data': {"hello": "world"}})
    
    

    {'url': 'https://postman-echo.com/post', 'data': {'hello': 'world'}}

    import json
    
    print(json.dumps({'url': 'https://postman-echo.com/post', 'data': {"hello": "world"}}))
    
    

    {"url": "https://postman-echo.com/post", "data": {"hello": "world"}}

    报价很重要,注意'" 的区别。

    【讨论】:

    • 澄清一下,我的确切问题是当我执行 pickle.dumps(json_data),然后尝试将其作为参数从 python 端传递给我的 rust 接口时,我无法反序列化它在生锈的一面。
    • 带单引号的 JSON 无效,因此 json 解析应该失败(在生锈方面)。您不是在腌制 json,而是腌制 pyhton 字典。
    • 如果我将它写入一个文件,并从生锈的一面读取它,它会完美运行。但是,当我尝试将其作为字符串而不是使用临时文件发送时,我遇到了相同过程的问题。
    猜你喜欢
    • 1970-01-01
    • 2012-10-27
    • 1970-01-01
    • 2021-10-31
    • 1970-01-01
    • 2022-11-19
    • 1970-01-01
    • 2020-07-30
    • 1970-01-01
    相关资源
    最近更新 更多