AgentsDock: Agentik AI Tahlili Uchun Maxsus IDE
AgentsDock — bu agentik AI tadqiqotchilari uchun maxsus ishlab chiqilgan IDE. Bu dastur Claude Code, Codex va Cursorni bir ekranda birlashtiradi.

Har safar Pydantic v2 bilan ma'lumotlarni tasdiqlasangiz, Rust kengaytmasi ishini bajaradi. Pydantic-core, bu dasturning asosi, PyO3 vositalari yordamida yaratilgan. Bu maqola shu turdagi ko'prikni yaratish jarayonini tushuntiradi: Rust tilida yozilgan JSON parserni Python ilovasida ishlatish.
Rust kodini Python ilovasida ishlatish uchun to'rtta asosiy qadam bor:
Rustda #[pyfunction] va #[pymodule] makroslari bu bog'lovchi vazifasini bajaradi. Bu makroslar Python dekoratorlariga o'xshaydi: ular ustiga joylashtirilgan funksiyani qayta yozadi va Python obyektlariga chaqirishni, tur konvertatsiyalarini va referentsiya sanashni boshqaradi.
Maturin Rust paketini umumiy kutubxona (.so, .dylib, .dll) sifatida to'playdi va sizning virtual muhitga joylashtiradi, shunda import qilish oddiy bo'ladi. Bu jarayonni How to run Rust in Python with PyO3 and Maturin maqolasida batafsil ko'rsatilgan.
Bu parser Rust qiymatini birinchi navbatda yaratadi. Bu qiymat JSON daraxti shaklida bo'lib, bu postning qolgan qismida misol sifatida ishlatiladi. Rust tilida JSON parser yozish kursida talabalar JSON parserni Rust tilida yozishni o'rgatiladi, keyin esa uni PyO3 yordamida Python ilovasida ishlatishni o'rgatiladi.
pub enum JsonValue {
Null,
Boolean(bool),
Number(f64),
String(String),
Array(Vec<JsonValue>),
Object(HashMap<String, JsonValue>),
}
Parser tomonidan yaratilgan Rust enumi JSON daraxtini to'liq tasvirlaydi:
pub enum JsonValue {
Null,
Boolean(bool),
Number(f64),
String(String),
Array(Vec<JsonValue>),
Object(HashMap<String, JsonValue>),
}
Bu daraxt faqat Rustda yashaydi. Python bu daraxtni hech qachon ko'rmaydi. PyO3 qatlami bu daraxt uchun ingichka moslashuvdir.
Funksiyani Python ilovasida ishlatish uchun ikkita qator kerak:
#[pyfunction]
fn parse_json<'py>(py: Python<'py>, input: &str) -> PyResult<Bound<'py, PyAny>> {
parse(input)?.into_pyobject(py)
}
#[pyfunction]
fn parse_json<'py>(py: Python<'py>, input: &str) -> PyResult<PyObject> {
parse(input)?.into_pyobject(py)
}
Bu funksiyaning imzosi Python o'quvchisi uchun eng qiziq qismdir:
Shuning uchun parse(input)? asl ishni bajaradi, va .into_pyobject(py) so'ralgan Python obyektlarini yaratadi. Bu oxirgi chaqirishda xarajat yashirin: u daraxtning tugunlarida Python obyektlarini yaratishi kerak bo'ladi, va katta hujjatda bu ishning o'zidan ko'proq ishni talab qilishi mumkin.
.into_pyobject butun JsonValue daraxtini kuzatadi va uni Python obyektlariga qayta quradi: har bir obyekt uchun dict, har bir massiv uchun list, har bir barg uchun float yoki str. Siz ushbu tarjimaning amalga oshirilishini IntoPyObject traitini amalga oshirib berasiz, PyO3 bu traitni Rust qiymatini Python qiymatiga aylantirish uchun chaqiradi:
impl<'py> IntoPyObject<'py> for JsonValue {
fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
match self {
JsonValue::Null => Ok(py.None().into_bound(py)),
JsonValue::Number(n) => Ok(n.into_pyobject(py)?.to_owned().into_any()),
JsonValue::Object(obj) => {
let py_dict = PyDict::new(py);
for (k, v) in obj {
py_dict.set_item(k, v.into_pyobject(py)?)?; // recurses
}
Ok(py_dict.into_any())
}
// ...arrays, strings, booleans
}
}
}
impl<'py> IntoPyObject<'py> for JsonValue {
fn into_pyobject(self, py: Python<'py>) -> Result<PyObject, PyErr> {
match self {
JsonValue::Null => Ok(py.None().into_bound(py)),
JsonValue::Number(n) => Ok(n.into_pyobject(py)?.to_owned().into_any()),
JsonValue::Object(obj) => {
let py_dict = PyDict::new(py);
for (k, v) in obj {
py_dict.set_item(k, v.into_pyobject(py)?)?; // rekursiv
}
Ok(py_dict.into_any())
}
// ...arrays, strings, booleans
}
}
}
100 000 qiymatli hujjat 100 000 dan ortiq Python obyektlarini yaratishni anglatadi, bu butun parsdan keyin sodir bo'ladi. Kattaroq hujjatlarda bu materializatsiya tsikli, pars emas, umuman vaqtni belgilaydi.
Qaytish qiymati yagona narsa emas, bu tarjimalash kerak bo'lgan narsadir. Pars xatosi turlangan Rust xatosi bo'lib, Python istisnosi kerak. Bir From impl, bu Rust turini boshqa turga aylantirish uchun ishlatiladigan trait, ? operatoriga ishini bajarish uchun ishlatiladi:
impl From<JsonError> for PyErr {
fn from(err: JsonError) -> PyErr {
match err {
JsonError::UnterminatedString { position } => PyValueError::new_err(
format!("Unterminated string starting at position {position}")
),
// ...har bir xato variant uchun bir tarmoq, pozitsiya saqlanadi
}
}
}
Shu bilan noto'g'ri kiritilgan ma'lumot ValueError istisnosini keltirib chiqaradi, bu yerda pars buzilgan joyda ofsetni olib yuradi. Fayl o'qish yo'li ham shu tarzda ishlaydi: std::io::Error allaqachon mos Python istisnosiga aylantiriladi, shuning uchun yo'q fayl FileNotFoundError istisnosini keltirib chiqaradi.
impl From<JsonError> for PyErr {
fn from(err: JsonError) -> PyErr {
match err {
JsonError::UnterminatedString { position } => PyValueError::new_err(
format!("Unterminated string starting at position {position}")
),
// ...one arm per error variant, position preserved
}
}
}
Chaqiruvchi Python semantikasini oladi, Rust qatlami o'tmaydi.
Agar siz portlayotgan Rust funksiyasi skalyar qiymat qaytarsa, uni portlaying va davom eting. Chegara odatda kichik bo'ladi va unga e'tibor bermaslik mumkin.
Agar u katta tuzilma qaytarsa, konvertatsiya sizning asl xarajat bo'ladi, va bu parser o'zini tezlashtirgandan keyin optimallashtirish uchun keyingi narsa bo'ladi. PyDict ni oldindan ajratish cheklangan darajada yordam berishi mumkin, lekin katta yutuq arxitekturaviy: agar chaqiruvchi butun daraxtni ko'rmasa, uni butunlay materializatsiya qilmang. Rust orqali kechikishli, faqat zarur bo'lgan qismini qaytarib bering.
Asl manba: belderbos.dev