- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试将这个向辅助进程发送和接收输入的 Python 脚本移植到 Rust:
import subprocess
data = chr(0x3f) * 1024 * 4096
child = subprocess.Popen(['cat'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
output, _ = child.communicate(data)
assert output == data
在输入缓冲区超过 64k 之前,我的尝试工作正常,因为大概操作系统的管道缓冲区在输入被写入之前就已经填满了。
use std::io::Write;
const DATA: [u8; 1024 * 4096] = [0x3f; 1024 * 4096];
fn main() {
let mut child = std::process::Command::new("cat")
.stdout(std::process::Stdio::piped())
.stdin(std::process::Stdio::piped())
.spawn()
.unwrap();
match child.stdin {
Some(ref mut stdin) => {
match stdin.write_all(&DATA[..]) {
Ok(_size) => {}
Err(err) => panic!(err),
}
}
None => unreachable!(),
}
let res = child.wait_with_output();
assert_eq!(res.unwrap().stdout.len(), DATA.len())
}
Rust 中是否有等效的 subprocess.communicate
?也许是一个 select
等价物?可以用mio来解决这个问题吗?另外,似乎没有办法关闭标准输入。
这里的目标是构建一个高性能系统,所以我想避免为每个任务生成一个线程。
最佳答案
好吧,完成这项工作需要大量代码,我需要 mio 和 nix 的组合,因为当它们是管道时,mio 不会将 AsRawFd 项目设置为非阻塞,所以必须这样做首先。
这是结果
extern crate mio;
extern crate bytes;
use mio::*;
use std::io;
use mio::unix::{PipeReader, PipeWriter};
use std::process::{Command, Stdio};
use std::os::unix::io::AsRawFd;
use nix::fcntl::FcntlArg::F_SETFL;
use nix::fcntl::{fcntl, O_NONBLOCK};
extern crate nix;
struct SubprocessClient {
stdin: PipeWriter,
stdout: PipeReader,
output : Vec<u8>,
input : Vec<u8>,
input_offset : usize,
buf : [u8; 65536],
}
// Sends a message and expects to receive the same exact message, one at a time
impl SubprocessClient {
fn new(stdin: PipeWriter, stdout : PipeReader, data : &[u8]) -> SubprocessClient {
SubprocessClient {
stdin: stdin,
stdout: stdout,
output : Vec::<u8>::new(),
buf : [0; 65536],
input : data.to_vec(),
input_offset : 0,
}
}
fn readable(&mut self, _event_loop: &mut EventLoop<SubprocessClient>) -> io::Result<()> {
println!("client socket readable");
match self.stdout.try_read(&mut self.buf[..]) {
Ok(None) => {
println!("CLIENT : spurious read wakeup");
}
Ok(Some(r)) => {
println!("CLIENT : We read {} bytes!", r);
self.output.extend(&self.buf[0..r]);
}
Err(e) => {
return Err(e);
}
};
return Ok(());
}
fn writable(&mut self, event_loop: &mut EventLoop<SubprocessClient>) -> io::Result<()> {
println!("client socket writable");
match self.stdin.try_write(&(&self.input)[self.input_offset..]) {
Ok(None) => {
println!("client flushing buf; WOULDBLOCK");
}
Ok(Some(r)) => {
println!("CLIENT : we wrote {} bytes!", r);
self.input_offset += r;
}
Err(e) => println!("not implemented; client err={:?}", e)
}
if self.input_offset == self.input.len() {
event_loop.shutdown();
}
return Ok(());
}
}
impl Handler for SubprocessClient {
type Timeout = usize;
type Message = ();
fn ready(&mut self, event_loop: &mut EventLoop<SubprocessClient>, token: Token,
events: EventSet) {
println!("ready {:?} {:?}", token, events);
if events.is_readable() {
let _x = self.readable(event_loop);
}
if events.is_writable() {
let _y = self.writable(event_loop);
}
}
}
pub fn from_nix_error(err: ::nix::Error) -> io::Error {
io::Error::from_raw_os_error(err.errno() as i32)
}
fn set_nonblock(s: &AsRawFd) -> io::Result<()> {
fcntl(s.as_raw_fd(), F_SETFL(O_NONBLOCK)).map_err(from_nix_error)
.map(|_| ())
}
const TEST_DATA : [u8; 1024 * 4096] = [40; 1024 * 4096];
pub fn echo_server() {
let mut event_loop = EventLoop::<SubprocessClient>::new().unwrap();
let process =
Command::new("cat")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn().unwrap();
let raw_stdin_fd;
match process.stdin {
None => unreachable!(),
Some(ref item) => {
let err = set_nonblock(item);
match err {
Ok(()) => {},
Err(e) => panic!(e),
}
raw_stdin_fd = item.as_raw_fd();
},
}
let raw_stdout_fd;
match process.stdout {
None => unreachable!(),
Some(ref item) => {
let err = set_nonblock(item);
match err {
Ok(()) => {},
Err(e) => panic!(e),
}
raw_stdout_fd = item.as_raw_fd();},
}
//println!("listen for connections {:?} {:?}", , process.stdout.unwrap().as_raw_fd());
let mut subprocess = SubprocessClient::new(PipeWriter::from(Io::from_raw_fd(raw_stdin_fd)),
PipeReader::from(Io::from_raw_fd(raw_stdout_fd)),
&TEST_DATA[..]);
let stdout_token : Token = Token(0);
let stdin_token : Token = Token(1);
event_loop.register(&subprocess.stdout, stdout_token, EventSet::readable(),
PollOpt::level()).unwrap();
// Connect to the server
event_loop.register(&subprocess.stdin, stdin_token, EventSet::writable(),
PollOpt::level()).unwrap();
// Start the event loop
event_loop.run(&mut subprocess).unwrap();
let res = process.wait_with_output();
match res {
Err(e) => {panic!(e);},
Ok(output) => {
subprocess.output.extend(&output.stdout);
println!("Final output was {:}\n", output.stdout.len());
},
}
println!("{:?}\n", subprocess.output.len());
}
fn main() {
echo_server();
}
基本上,关闭标准输入的唯一方法是调用 process.wait_with_output,因为标准输入没有关闭原语
一旦发生这种情况,剩余的输入可以扩展输出数据向量。
现在有一个箱子可以做到这一点
关于io - 相当于 Python 的 subprocess.communicate 在 Rust 中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37109336/
我在这里看到这个帖子很多次了;但未能从命令中捕获故意错误。迄今为止我找到的最好的部分工作.. from Tkinter import * import os import Image, ImageTk
我正在尝试使用 Python 在我的服务器上进行一些基本的模块设置。这有点困难,因为我无法访问互联网。 这是我的代码 import sys import os from subprocess impo
这个问题在这里已经有了答案: Why does passing variables to subprocess.Popen not work despite passing a list of ar
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
使用 subprocess.call 时,输出符合预期。 result = subprocess.call([securefx, '/NoPrompt', '/Q', '/RetryCount', r
当我使用 subprocess.Popen 或 subprocess.call 执行生成大量输出的命令行时,python 脚本挂起,但奇怪的是,等待一段时间后,脚本处于挂起状态,发现cmd命令的作业已
我是 subprocess 模块的新手,文档让我想知道 subprocess.popen 和 subprocess.run 之间有什么区别.命令的作用有区别吗?一个只是更新吗?哪个更好用? 最佳答案
我需要限制使用 subprocess.call 从 python 进程生成的外部命令行应用程序占用的时间和 CPU,主要是因为有时生成的进程会卡住并将 CPU 固定在 99%。 nice 和 ulim
我一直在使用 subprocess.check_output()有一段时间从子进程捕获输出,但在某些情况下遇到了一些性能问题。我在 RHEL6 机器上运行它。 调用 Python 环境是 linux
我想从 python 运行一个程序并找到它的内存使用情况。为此,我正在使用: l=['./a.out','','out.txt'] p=subprocess.Popen(l,shell=False,s
我正在使用 Python 2.7 我正在尝试从 Python 运行 StatTransfer 程序。 当我尝试时: tempname = os.path.abspath('./text.txt') T
我想执行以下操作: 使用 subprocess.check_call 从 Python 外壳到另一个可执行文件 捕获子进程的 stderr(如果有) 将 stderr 输出添加到父进程的 Called
我编写了一个程序(myProg.py),它使用subprocess模块通过run函数运行其他python程序。我注意到这些其他 python 程序中的 input(arg) 语句中的 arg 没有
我有这个小脚本可以让您的无线设备进入监控模式。它执行 airodump 扫描,然后在终止扫描后将输出转储到 file.txt 或变量,这样我就可以抓取 BSSID 和我可能需要的任何其他信息。 我觉得
我最近在 Python 中注意到 subprocess.Popen() 有一个参数: stdout=None(default) 我还看到有人使用 stdout=subprocess.PIPE。 有什么
我已经查看了它们的文档。 这个问题是由 J.F. 在这里的评论提示的:Retrieving the output of subprocess.call() subprocess.call() 的当前
我一直在尝试了解 subprocess.call 和 subprocess.run 之间的区别。我知道最后一个是 Python 3.5 上的新版本,两者都基于 subprocess.Popen,但我还
我无法得到它与 bash 相关或 python 子进程,但结果不同: >>> subprocess.Popen("echo $HOME", shell=True, stdout=subprocess.
我正在编写一个需要在 Linux 和 Windows 上运行并使用路径中存在的可执行文件(带参数)的程序。 (假设) 目前,我在使用 Subprocess.Call 和 Subprocess.Pope
当我的脚本有 .pyw扩展,函数 subprocess.Popen不起作用,但如果我使用 .py扩展,它的工作原理。其实扩展并不是那么重要,关键是我是否使用终端来运行脚本,如果我不使用它我有问题,否则
我是一名优秀的程序员,十分优秀!