std::time
: Работа с временем
2. std::process
: Управление процессами и внешними командами
3. std::env
: Доступ к окружению и аргументам
Практические советы
Пример: Комбинирование модулей
Упражнение
Заключение
В этом разделе мы разберём модули стандартной библиотеки Rust, связанные с обработкой времени и управлением процессами: std::time
, std::process
и std::env
. Эти инструменты позволяют измерять время, запускать внешние команды и взаимодействовать с окружающей средой программы. Лекция подойдёт как новичкам, так и опытным разработчикам, желающим углубить знания. Мы рассмотрим каждый модуль с примерами, нюансами и практическими советами.
std::time
: Работа с временемМодуль std::time
предоставляет типы для работы с временем: Duration
для интервалов, Instant
для измерения прошедшего времени и SystemTime
для работы с системными часами.
Duration
Duration
представляет промежуток времени с наносекундной точностью.
Пример: создание и использование Duration
:
use std::time::Duration;
fn main() {
let duration = Duration::from_secs(5); // 5 секунд
println!("Секунды: {}", duration.as_secs()); // 5
println!("Наносекунды: {}", duration.as_nanos()); // 5_000_000_000
let extra = Duration::from_millis(500); // 500 миллисекунд
let total = duration + extra;
println!("Всего: {:.2} сек", total.as_secs_f64()); // 5.50 сек
}
Комментарии:
from_secs
, from_millis
— удобные конструкторы.as_secs_f64
возвращает длительность в секундах как f64
.+
, -
).Instant
Instant
используется для измерения времени выполнения кода (монотонные часы).
Пример: замер времени:
use std::time::Instant;
use std::thread;
fn main() {
let start = Instant::now();
thread::sleep(Duration::from_secs(1));
let elapsed = start.elapsed();
println!("Прошло: {:.2} сек", elapsed.as_secs_f64()); // ~1.00 сек
}
Комментарии:
now
фиксирует текущий момент.elapsed
возвращает Duration
от момента создания.SystemTime
SystemTime
представляет момент времени относительно системных часов (может быть неточным из-за корректировок).
Пример: работа с датой:
use std::time::{SystemTime, UNIX_EPOCH};
fn main() -> std::io::Result<()> {
let now = SystemTime::now();
let since_epoch = now.duration_since(UNIX_EPOCH)?;
println!("Секунд с эпохи: {}", since_epoch.as_secs());
let earlier = UNIX_EPOCH + Duration::from_secs(1_000_000_000);
println!("Прошло с 2001-09-09? {}",
now.duration_since(earlier).unwrap().as_secs());
Ok(())
}
Комментарии:
duration_since
возвращает Result
, так как время может быть "в прошлом".UNIX_EPOCH
— это 1 января 1970 года, 00:00 UTC.Предупреждение: SystemTime
может быть неточным из-за изменений системных часов. Для замеров используйте Instant
.
std::process
: Управление процессами и внешними командамиМодуль std::process
позволяет запускать внешние процессы, взаимодействовать с их вводом-выводом и получать код завершения.
Основные типы и функции:
Command
: Построение команды.Output
: Результат выполнения (stdout, stderr, код).exit
: Завершение текущего процесса.Пример: запуск команды ls
(или dir
на Windows):
use std::process::Command;
fn main() -> std::io::Result<()> {
let output = if cfg!(target_os = "windows") {
Command::new("cmd").args(&["/C", "dir"]).output()?
} else {
Command::new("ls").arg("-l").output()?
};
println!("Статус: {}", output.status);
println!("Вывод: {}", String::from_utf8_lossy(&output.stdout));
if !output.stderr.is_empty() {
println!("Ошибки: {}", String::from_utf8_lossy(&output.stderr));
}
Ok(())
}
Комментарии:
cfg!
обеспечивает кроссплатформенность.output()
возвращает Output
с полями status
, stdout
, stderr
.from_utf8_lossy
преобразует байты в строку, заменяя некорректные символы.std::env
: Доступ к окружению и аргументамМодуль std::env
предоставляет доступ к переменным окружения, аргументам командной строки и текущему каталогу.
Основные функции:
args
: Аргументы командной строки.var
: Получение переменной окружения.current_dir
: Текущая рабочая директория.Пример: чтение аргументов и переменных:
use std::env;
fn main() -> std::io::Result<()> {
// Аргументы командной строки
let args: Vec = env::args().collect();
println!("Аргументы: {:?}", args);
// Переменная окружения
match env::var("PATH") {
Ok(path) => println!("PATH: {}", path),
Err(e) => println!("Ошибка PATH: {}", e),
}
// Текущая директория
let dir = env::current_dir()?;
println!("Текущая директория: {:?}", dir);
Ok(())
}
Комментарии:
args()
возвращает итератор, первый элемент — путь к программе.var
возвращает Result
, так как переменная может отсутствовать.current_dir
возвращает PathBuf
.Заметка: Используйте env::args_os
вместо args
, если нужны сырые строки ОС (например, для некорректного UTF-8).
std::time
: Используйте Instant
для замеров производительности, а SystemTime
— для работы с календарным временем.std::process
: Проверяйте status.success()
, чтобы убедиться в успешном выполнении команды.std::env
: Обрабатывайте отсутствие переменных с помощью unwrap_or
для значений по умолчанию.Программа, измеряющая время выполнения команды:
use std::env;
use std::process::Command;
use std::time::Instant;
fn main() -> std::io::Result<()> {
let args: Vec = env::args().collect();
if args.len() < 2 {
println!("Укажите команду, например: cargo run -- ls");
return Ok(());
}
let cmd = &args[1];
let start = Instant::now();
let output = Command::new(cmd).output()?;
let elapsed = start.elapsed();
println!("Статус: {}", output.status);
println!("Время выполнения: {:.2} сек", elapsed.as_secs_f64());
println!("Вывод: {}", String::from_utf8_lossy(&output.stdout));
Ok(())
}
Этот пример использует env
для аргументов, process
для запуска команды и time
для замера времени.
Напишите программу, которая:
std::env::args
.std::process::Command
.Instant
.Result
.Подсказка: Используйте take
для ограничения вывода.
Модули std::time
, std::process
и std::env
предоставляют всё необходимое для работы с временем, процессами и окружением. Они просты в использовании, но требуют внимания к обработке ошибок и кроссплатформенности. Освоив их, вы сможете создавать утилиты, скрипты и приложения с внешними зависимостями. Далее мы рассмотрим сетевые возможности.
Выполните упражнение или двигайтесь дальше!