Mundarija (21)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Til va implementatsiya
- 2.2. Asosiy implementatsiyalar
- 2.3. PyPy va JIT
- 2.4. CPython'ga xos farazlar
- 2.5. Implementatsiyani aniqlash
- 2.6. MicroPython cheklovlari
- 2.7. Qachon qaysi biri
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Implementatsiya va imkoniyatlarni aniqlash
- Misol 2 — CPython'ga xos farazlar va ularning ko'chuvchan muqobillari
- Misol 3 — Ko'chuvchanlik tekshiruvchisi
- Misol 4 — Amaliy: bir kod, to'rt muhit
- 5. To'g'ri va noto'g'ri tushunishlar
- 6. Keng tarqalgan xatolar va yechimlari
- 7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8. Eng yaxshi amaliyotlar
- 9. Amaliy topshiriq
- Xulosa
12.7-dars: Alternativ interpretatorlar: PyPy, MicroPython
12-QISM — CPYTHON ICHKI TUZILISHI · 7-dars
1. Kirish va motivatsiya
Shu paytgacha "Python" deganda CPython ni nazarda tutdik: havolalar sanog'i, GIL, bayt-kod, PyObject. Lekin Python — bu til spetsifikatsiyasi, CPython esa uning eng mashhur implementatsiyasi. Boshqalari ham bor va ular boshqacha qarorlar qabul qilgan.
Real vaziyat. Narxlarni hisoblaydigan xizmat sof Python sikllarda kuniga 40 daqiqa ishlardi. Jamoa kodni o'zgartirmasdan PyPy da ishga tushirdi — 6 daqiqa. Lekin ikkinchi xizmat (NumPy va psycopg ga tayangan) PyPy da sekinlashdi va bir nechta kutubxona umuman ishlamadi.
Uchinchi vaziyat: IoT qurilmasi uchun sensor kodi yozildi. Mikrokontrollerda 264 KB operativ xotira bor — CPython u yerga sig'maydi. MicroPython esa sig'adi, lekin pandas u yerda yo'q va float 32 bitli.
Shuning uchun "Python kodim qayerda ishlaydi?" degan savol jiddiy: u yozgan kodingiz qaysi farazlarga tayanishiga bog'liq.
Bu darsda:
- Til va implementatsiya farqi; spetsifikatsiya nimani kafolatlaydi
- Asosiy implementatsiyalar: CPython, PyPy, MicroPython, GraalPy, Pyodide va boshqalar
- PyPy JIT qanday ishlaydi: isitish, iz (trace), deoptimizatsiya
- CPython'ga xos farazlar:
__del__vaqti,id(), interning, GIL atomarligi - Implementatsiyani va imkoniyatlarni aniqlash
- MicroPython cheklovlari: xotira,
float, standart kutubxona - Amaliy: kodning ko'chuvchanligini tekshiruvchi
2. Nazariya — chuqur tushuntirish
2.1. Til va implementatsiya
| Nima | |
|---|---|
| Til spetsifikatsiyasi | Sintaksis, semantika, standart kutubxona hujjatlari — "Language Reference" |
| Implementatsiya | Shu qoidalarni bajaradigan dastur: CPython, PyPy, MicroPython, ... |
| Implementatsiya tafsiloti | Hujjatlarda "CPython implementation detail" deb belgilangan xulq |
Spetsifikatsiya kafolatlaydi: dict kiritish tartibini saqlaydi (3.7+), int cheksiz, // yaxlitlash, istisnolar semantikasi, with protokoli.
Spetsifikatsiya kafolatlamaydi: obyekt qachon o'chishi, id() ning ma'nosi, satrlar interningi, list.append ning atomarligi, sys.getsizeof natijasi.
2.2. Asosiy implementatsiyalar
| Implementatsiya | Asosi | Kuchli tomoni | Cheklovi |
|---|---|---|---|
| CPython | C | Etalon, butun ekotizim, C API | Sof Python tezligi past, GIL |
| PyPy | RPython + izli (tracing) JIT | Uzoq ishlaydigan sof Python kodda 5–20 barobar tez | C kengaytmalar sekin (cpyext), xotira ko'proq, isitish kerak |
| MicroPython | C, mikrokontrollerlar uchun | Bir necha yuz KB xotirada ishlaydi | Kutubxonalarning kichik qismi, cheklangan turlar |
| CircuitPython | MicroPython forki | Ta'lim va elektronika uchun qulay | Xuddi shunday cheklovlar |
| GraalPy | GraalVM (Java) | Java ekotizimi bilan integratsiya, JIT | Yosh, ba'zi kutubxonalar ishlamaydi |
| Pyodide | CPython → WebAssembly | Brauzerda ishlaydi, NumPy/pandas bor | Sekinroq, tarmoq va fayl cheklovlari |
| RustPython | Rust | O'rganish, WASM tajribalari | To'liq emas |
| IronPython | .NET | .NET integratsiyasi | Ekotizim cheklangan |
Kompilyatorlar (interpretator emas, lekin shu qatorda eslanadi): Cython (Python → C), Nuitka (Python → C++ binar), mypyc — ular CPython ustida ishlaydi va mos kod talab qiladi (19, 30-qismlar).
2.3. PyPy va JIT
Izli (tracing) JIT: interpretator tez-tez bajariladigan sikl izlarini kuzatadi, ularni mashina kodiga kompilyatsiya qiladi va turlar haqidagi farazlarni "qo'riqchi" (guard) tekshiruvlari bilan himoyalaydi. Faraz buzilsa — deoptimizatsiya, interpretatorga qaytish.
| Xususiyat | Oqibat |
|---|---|
| Isitish (warm-up) | Dastlabki soniyalar sekin; qisqa skriptlarda PyPy foyda bermaydi |
| Sof Python sikllar | Eng katta yutuq shu yerda |
| C kengaytmalar | cpyext qatlami orqali — ko'pincha sekinroq (NumPy ishlaydi, lekin CPython'dagidek emas) |
| Xotira | Odatda ko'proq (JIT kodi, obyekt modeli boshqacha) |
| Havolalar sanog'i yo'q | Obyektlar kechikib o'chadi — __del__ va fayl yopilishi kafolatlanmaydi |
| GIL | PyPy'da ham bor |
Qoida: PyPy — uzoq ishlaydigan, sof Python hisob-kitobga boy xizmatlar uchun; C kutubxonalarga tayangan kod uchun emas.
2.4. CPython'ga xos farazlar
| Faraz | CPython | Boshqa joyda |
|---|---|---|
| Oxirgi havola ketishi bilan obyekt o'chadi | (refcount) | PyPy, GraalPy — GC qachondir |
open(...).read() fayl darhol yopiladi |
Fayl deskriptori uzoq ochiq qoladi | |
id(obj) — xotira manzili |
Boshqa raqam | |
Kod konstantalari interned, is ishlaydi |
Boshqacha | |
list.append atomar |
(GIL) | Erkin ipli yig'ma, boshqa implementatsiyalar |
sys.getrefcount, sys._getframe |
Yo'q yoki boshqacha | |
ctypes.pythonapi, C kengaytmalar |
Yo'q yoki sekin | |
sys.getsizeof |
MicroPython'da yo'q |
Ko'chuvchan yozish:
with open(yol) as f: # ✅ aniq yopish — hamma joyda ishlaydi
matn = f.read()
matn = open(yol).read() # ❌ CPython'da ishlaydi, PyPy'da deskriptor qoladi2.5. Implementatsiyani aniqlash
sys.implementation.name # 'cpython', 'pypy', 'micropython', 'graalpy'
sys.implementation.version # implementatsiya versiyasi
platform.python_implementation() # 'CPython', 'PyPy', ...
sys.version_info # til versiyasi (hammasida bor)Imkoniyatni tekshiring, nomni emas:
if sys.implementation.name == "cpython": # ❌ mo'rt
...
if hasattr(sys, "getrefcount"): # ✅ imkoniyat bo'yicha
...
try:
import ujson as json # ✅ muqobil bilan
except ImportError:
import json2.6. MicroPython cheklovlari
| Jihat | MicroPython |
|---|---|
| Xotira | Bir necha o'n KB dan boshlab |
| Standart kutubxona | Kichik qismi: sys, time, json, os (qisqartirilgan), machine, network |
| Turlar | int cheksiz (ko'p portlarda), float odatda 32 bitli, complex bo'lmasligi mumkin |
| Yo'q narsalar | sys.getsizeof (ba'zi portlarda), inspect, typing (faqat stub), ko'p dunder tafsilotlar |
| Qo'shimcha | machine, network, bluetooth — apparatga kirish |
| Bayt-kod | O'z formati, .mpy fayllari |
Kod yozish uslubi: kam xotira ajratish, bytearray ni qayta ishlatish, generatorlar, global obyektlarni oldindan yaratish.
2.7. Qachon qaysi biri
| Vazifa | Tanlov |
|---|---|
| Umumiy backend, ma'lumot tahlili, ML | CPython (ekotizim) |
| Uzoq ishlaydigan sof Python hisob | PyPy (o'lchab) |
| Mikrokontroller, sensor | MicroPython / CircuitPython |
| Brauzerda Python | Pyodide |
| Java infratuzilmasi bilan integratsiya | GraalPy |
| Bitta faylli binar | Nuitka, PyInstaller (19-qism) |
| Issiq kodni tezlashtirish | Cython, C/Rust kengaytma (30-qism) |
3. Tez ma'lumotnoma
Aniqlash
sys.implementation.name / .version platform.python_implementation()
hasattr(sys, "getrefcount") try: import X except ImportError: ...Ko'chuvchanlik qoidalari
with / finalize → refcount ga tayanmang
== → is (qiymatlar uchun) o'rniga
qulflar → GIL atomarligiga tayanmang
id() → faqat identifikator, manzil emas
sys.getsizeof, ctypes, gc tafsilotlari → CPython'ga xosImplementatsiyalar
CPython (etalon) · PyPy (JIT, sof Python) · MicroPython (mikrokontroller)
GraalPy (JVM) · Pyodide (brauzer) · Cython/Nuitka (kompilyatorlar)4. Batafsil misollar
Misol 1 — Implementatsiya va imkoniyatlarni aniqlash
"""sys.implementation va platform; imkoniyatlarni tekshirish; nom bo'yicha emas, imkoniyat bo'yicha tarmoqlanish."""
import platform
import sys
def bor(nom, tekshiruv):
try:
return "✅" if tekshiruv() else "❌"
except Exception:
return "❌"
print("=== 1. Implementatsiya ===")
print(f" sys.implementation.name: {sys.implementation.name}")
print(f" platform.python_implementation(): {platform.python_implementation()}")
print(f" til versiyasi: {'.'.join(map(str, sys.version_info[:3]))}")
print(f" implementatsiya versiyasi ham bor: {hasattr(sys.implementation, 'version')}")
print(f" cache_tag: {sys.implementation.cache_tag}")
print("\n=== 2. Imkoniyatlar (boshqa implementatsiyalarda farq qiladi) ===")
IMKONIYATLAR = {
"sys.getrefcount": lambda: sys.getrefcount(object()) > 0,
"sys._getframe": lambda: sys._getframe() is not None,
"sys.getsizeof": lambda: sys.getsizeof(1) > 0,
"sys._is_gil_enabled": lambda: sys._is_gil_enabled() in (True, False),
"ctypes": lambda: __import__("ctypes").sizeof(__import__("ctypes").c_void_p) > 0,
"gc.get_referrers": lambda: isinstance(__import__("gc").get_referrers(object()), list),
"threading": lambda: __import__("threading").active_count() >= 1,
"dataclasses": lambda: __import__("dataclasses").is_dataclass(object) is False,
"decimal (C tezkor)": lambda: __import__("decimal").__file__ is not None,
}
for nom, tekshiruv in IMKONIYATLAR.items():
print(f" {nom:22} {bor(nom, tekshiruv)}")
print("\n=== 3. Nom bo'yicha emas, imkoniyat bo'yicha ===")
def tirikmi(obj_havola):
"""Obyekt tirikligini har joyda ishlaydigan usulda tekshirish."""
return obj_havola() is not None
def xotira_hisoboti(obj):
if hasattr(sys, "getsizeof"):
return f"{sys.getsizeof(obj)} bayt"
return "o'lchov mavjud emas (masalan, MicroPython)"
import weakref
class Yozuv:
pass
y = Yozuv()
havola = weakref.ref(y)
print(f" weakref bilan tirikligi: {tirikmi(havola)}")
del y
print(f" o'chirilgandan keyin: {tirikmi(havola)} ← CPython'da darhol, boshqa joyda GC dan keyin")
print(f" xotira hisoboti: {xotira_hisoboti([1, 2, 3])}")
print(f" JSON kutubxonasi: {'ujson' if 'ujson' in sys.modules else 'json'} (MicroPython'da ujson bo'lishi mumkin)")Natijaning muhim qismi:
=== 1. Implementatsiya ===
sys.implementation.name: cpython
platform.python_implementation(): CPython
til versiyasi: 3.14.5
implementatsiya versiyasi ham bor: True
cache_tag: cpython-314
=== 2. Imkoniyatlar (boshqa implementatsiyalarda farq qiladi) ===
sys.getrefcount ✅
sys._getframe ✅
sys.getsizeof ✅
sys._is_gil_enabled ✅
ctypes ✅
gc.get_referrers ✅
threading ✅
dataclasses ✅
decimal (C tezkor) ✅
=== 3. Nom bo'yicha emas, imkoniyat bo'yicha ===
weakref bilan tirikligi: True
o'chirilgandan keyin: False ← CPython'da darhol, boshqa joyda GC dan keyin
xotira hisoboti: 88 bayt
JSON kutubxonasi: json (MicroPython'da ujson bo'lishi mumkin)Nima ko'rsatdi: 2.1, 2.5-bo'limlar.
Misol 2 — CPython'ga xos farazlar va ularning ko'chuvchan muqobillari
"""__del__ vaqti: refcount va GC; sikl orqali 'PyPy kabi' kechikishni ko'rsatish; id(), interning, GIL atomarligi; to'g'ri yozish usullari."""
import gc
import sys
import weakref
jurnal = []
class Fayl:
"""Resursni __del__ da yopadigan (yomon) sinf."""
def __init__(self, nom):
self.nom = nom
jurnal.append(f"ochildi:{nom}")
def __del__(self):
jurnal.append(f"yopildi:{self.nom}")
print("=== 1. __del__ qachon ishlaydi ===")
f = Fayl("hisobot.csv")
del f
print(f" refcount nolga tushdi → darhol: {jurnal}")
jurnal.clear()
a, b = Fayl("a.log"), Fayl("b.log")
a.juft, b.juft = b, a # sikl: refcount yetarli emas
del a, b
print(f" sikl ichida, gc.collect() dan oldin: {[x for x in jurnal if x.startswith('yopildi')]}")
gc.collect()
print(f" gc.collect() dan keyin: {[x for x in jurnal if x.startswith('yopildi')]}")
print(" ⭐ PyPy va GraalPy'da refcount yo'q — oddiy holat ham shunday 'kechikadi'")
print("\n=== 2. Ko'chuvchan yechim ===")
jurnal.clear()
class Xavfsiz:
def __init__(self, nom):
self.nom = nom
jurnal.append(f"ochildi:{nom}")
def yop(self):
if self.nom:
jurnal.append(f"yopildi:{self.nom}")
self.nom = None
def __enter__(self):
return self
def __exit__(self, *xato):
self.yop()
return False
with Xavfsiz("tranzaksiya.db") as x:
pass
print(f" with bloki: {jurnal} ← implementatsiyadan qat'i nazar aniq vaqtda")
jurnal.clear()
x = Xavfsiz("kesh.bin")
weakref.finalize(x, jurnal.append, "yopildi:kesh.bin (finalize)")
del x
print(f" weakref.finalize zaxira sifatida: {jurnal}")
print("\n=== 3. Boshqa farazlar ===")
s1 = "".join(["so", "liq"])
s2 = "soliq"
print(f" id() — CPython'da manzil: {id(s2) > 0}, lekin ma'nosi implementatsiyaga bog'liq")
print(f" ish vaqtidagi satr konstanta bilan bitta obyektmi: {s1 is s2} (11.7-dars), teng: {s1 == s2}")
print(f" {'✅ == ishlatildi' if s1 == s2 else ''} — 'is' ni qiymat uchun ishlatmang")
kichik = 256
print(f" kichik sonlar keshi CPython tafsiloti: {kichik is int('256')}")
print(f" sys.getrefcount mavjud: {hasattr(sys, 'getrefcount')} — PyPy'da yo'q, kod unga tayanmasin")
print(" list.append atomarligi GIL ga bog'liq 12.5-bob — qulf ishlating")Natijaning muhim qismi:
=== 1. __del__ qachon ishlaydi ===
refcount nolga tushdi → darhol: ['ochildi:hisobot.csv', 'yopildi:hisobot.csv']
sikl ichida, gc.collect() dan oldin: []
gc.collect() dan keyin: ['yopildi:a.log', 'yopildi:b.log']
⭐ PyPy va GraalPy'da refcount yo'q — oddiy holat ham shunday 'kechikadi'
=== 2. Ko'chuvchan yechim ===
with bloki: ['ochildi:tranzaksiya.db', 'yopildi:tranzaksiya.db'] ← implementatsiyadan qat'i nazar aniq vaqtda
weakref.finalize zaxira sifatida: ['ochildi:kesh.bin', 'yopildi:kesh.bin (finalize)']
=== 3. Boshqa farazlar ===
id() — CPython'da manzil: True, lekin ma'nosi implementatsiyaga bog'liq
ish vaqtidagi satr konstanta bilan bitta obyektmi: False (11.7-dars), teng: True
✅ == ishlatildi — 'is' ni qiymat uchun ishlatmang
kichik sonlar keshi CPython tafsiloti: True
sys.getrefcount mavjud: True — PyPy'da yo'q, kod unga tayanmasin
list.append atomarligi GIL ga bog'liq 12.5-bob — qulf ishlatingNima ko'rsatdi: 2.4-bo'lim — siklli obyektlar CPython'da ham "kechikib" o'chadi; bu PyPy semantikasining kichik namunasi.
Misol 3 — Ko'chuvchanlik tekshiruvchisi
"""AST bilan manbani tekshirish: CPython'ga xos API lar, xavfli naqshlar va MicroPython'da yo'q modullar."""
import ast
CPYTHON_API = {
"sys.getrefcount": "havolalar sanog'i — faqat CPython",
"sys._getframe": "freymlar — PyPy'da cheklangan",
"sys.getsizeof": "MicroPython'da yo'q",
"ctypes.pythonapi": "C API — faqat CPython",
"gc.get_referrers": "GC tafsiloti — implementatsiyaga bog'liq",
"gc.get_objects": "GC tafsiloti",
}
MICROPYTHON_YOQ = {"pandas", "numpy", "inspect", "dataclasses", "typing", "sqlite3", "multiprocessing", "concurrent"}
class Tekshiruvchi(ast.NodeVisitor):
def __init__(self):
self.topilmalar = []
def qayd(self, tugun, tur, matn):
self.topilmalar.append((tugun.lineno, tur, matn))
def visit_Attribute(self, tugun):
nom = ast.unparse(tugun)
if nom in CPYTHON_API:
self.qayd(tugun, "CPython API", f"{nom} — {CPYTHON_API[nom]}")
self.generic_visit(tugun)
def visit_Import(self, tugun):
for a in tugun.names:
if a.name.split(".")[0] in MICROPYTHON_YOQ:
self.qayd(tugun, "MicroPython'da yo'q", a.name)
self.generic_visit(tugun)
def visit_ImportFrom(self, tugun):
if tugun.module and tugun.module.split(".")[0] in MICROPYTHON_YOQ:
self.qayd(tugun, "MicroPython'da yo'q", tugun.module)
self.generic_visit(tugun)
def visit_Compare(self, tugun):
for op, tomon in zip(tugun.ops, tugun.comparators):
if isinstance(op, (ast.Is, ast.IsNot)) and isinstance(tomon, ast.Constant) and tomon.value is not None:
self.qayd(tugun, "is bilan qiymat", f"{ast.unparse(tugun)} — == ishlating 11.2-bob")
self.generic_visit(tugun)
def visit_FunctionDef(self, tugun):
if tugun.name == "__del__":
self.qayd(tugun, "__del__ ga tayanish", "resursni with yoki weakref.finalize bilan yoping")
self.generic_visit(tugun)
def visit_Call(self, tugun):
# open(...).read() — fayl aniq yopilmaydi
if isinstance(tugun.func, ast.Attribute) and isinstance(tugun.func.value, ast.Call):
ichki = tugun.func.value.func
if isinstance(ichki, ast.Name) and ichki.id == "open" and tugun.func.attr in {"read", "readlines", "write"}:
self.qayd(tugun, "yopilmagan fayl", f"{ast.unparse(tugun)[:40]} — with ishlating")
self.generic_visit(tugun)
MANBA = '''
import sys, gc, ctypes
import pandas as pd
from dataclasses import dataclass
def kesh_hajmi(kesh):
return sys.getsizeof(kesh)
def nusxalar(obj):
return sys.getrefcount(obj) - 1
class Ulanish:
def __del__(self):
self.soket.close()
def sozlama_oqi(yol):
matn = open(yol).read()
if matn is "":
return {}
return matn
def freym():
return sys._getframe(1).f_code.co_name
'''
daraxt = ast.parse(MANBA)
tekshiruvchi = Tekshiruvchi()
tekshiruvchi.visit(daraxt)
print("=== Ko'chuvchanlik hisoboti ===")
for qator, tur, matn in sorted(tekshiruvchi.topilmalar):
print(f" qator {qator:>2} {tur:22} {matn}")
print(f"\n jami: {len(tekshiruvchi.topilmalar)} ta ogohlantirish")
turlar = {}
for _, tur, _ in tekshiruvchi.topilmalar:
turlar[tur] = turlar.get(tur, 0) + 1
print(f" turlar bo'yicha: {dict(sorted(turlar.items()))}")Natijaning muhim qismi:
=== Ko'chuvchanlik hisoboti ===
qator 3 MicroPython'da yo'q pandas
qator 4 MicroPython'da yo'q dataclasses
qator 7 CPython API sys.getsizeof — MicroPython'da yo'q
qator 10 CPython API sys.getrefcount — havolalar sanog'i — faqat CPython
qator 13 __del__ ga tayanish resursni with yoki weakref.finalize bilan yoping
qator 17 yopilmagan fayl open(yol).read() — with ishlating
qator 18 is bilan qiymat matn is '' — == ishlating 11.2-bob
qator 23 CPython API sys._getframe — freymlar — PyPy'da cheklangan
jami: 8 ta ogohlantirish
turlar bo'yicha: {'CPython API': 3, "MicroPython'da yo'q": 2, '__del__ ga tayanish': 1, 'is bilan qiymat': 1, 'yopilmagan fayl': 1}Nima ko'rsatdi: 2.4-bo'lim — is bilan taqqoslash va __del__ ga tayanish CPython'da "ishlaydi", boshqa joyda esa yo'q.
Misol 4 — Amaliy: bir kod, to'rt muhit
Sensor ma'lumotlarini yig'adigan modul uchta joyda ishlashi kerak: server (CPython), mikrokontroller (MicroPython) va brauzer (Pyodide). Yechim — imkoniyatlarni aniqlash va muqobillar bilan moslashuvchan qatlam.
"""Muhit qatlamini imkoniyatlar bo'yicha qurish; MicroPython uslubidagi cheklangan muhitni taqlid qilib sinash."""
import sys
def muhit_yasa(mavjud_modullar=None, imkoniyatlar=None):
"""mavjud_modullar=None — haqiqiy muhit; aks holda taqlid (simulyatsiya)."""
haqiqiy = mavjud_modullar is None
bor = (lambda nom: nom in sys.modules or _import_mumkinmi(nom)) if haqiqiy else (lambda nom: nom in mavjud_modullar)
imkon = (lambda nom: hasattr(sys, nom)) if haqiqiy else (lambda nom: nom in (imkoniyatlar or set()))
return {
"nom": sys.implementation.name if haqiqiy else "taqlid",
"json": "json" if bor("json") else ("ujson" if bor("ujson") else "yo'q"),
"vaqt_aniqligi": "ns" if imkon("_getframe") and bor("time") else "s",
"xotira_olchovi": bool(imkon("getsizeof")),
"iplar": bor("threading"),
"saqlash": "sqlite3" if bor("sqlite3") else "fayl",
}
def _import_mumkinmi(nom):
try:
__import__(nom)
return True
except ImportError:
return False
class Yigʻuvchi:
"""Muhitga moslashadigan sensor yig'uvchi."""
def __init__(self, muhit, bufer_hajmi=4):
self.muhit = muhit
self.bufer = []
self.bufer_hajmi = bufer_hajmi
self.yozilgan = []
def olch(self, qiymat):
self.bufer.append(round(qiymat, 2))
if len(self.bufer) >= self.bufer_hajmi:
self.yuborish()
def yuborish(self):
if not self.bufer:
return
if self.muhit["json"] != "yo'q":
import json
yuk = json.dumps({"qiymatlar": self.bufer})
else:
yuk = "|".join(str(q) for q in self.bufer) # JSON bo'lmasa — oddiy format
self.yozilgan.append((self.muhit["saqlash"], yuk))
self.bufer = [] # yangi ro'yxat emas, tozalash ham mumkin — MicroPython'da xotira muhim
SERVER = None
MIKRO = ({"ujson", "time", "machine"}, set())
BRAUZER = ({"json", "time", "asyncio"}, {"getsizeof"})
MINIMAL = ({"time", "machine"}, set()) # JSON umuman yo'q port
print("=== 1. Muhitlar ===")
muhitlar = {
"CPython (haqiqiy)": muhit_yasa(),
"MicroPython (taqlid)": muhit_yasa(*MIKRO),
"Pyodide (taqlid)": muhit_yasa(*BRAUZER),
"Minimal port (taqlid)": muhit_yasa(*MINIMAL),
}
for nom, m in muhitlar.items():
print(f" {nom:22} json={m['json']:5} xotira_olchovi={str(m['xotira_olchovi']):5} iplar={str(m['iplar']):5} saqlash={m['saqlash']}")
print("\n=== 2. Bir xil kod, to'rt muhit ===")
for nom, m in muhitlar.items():
yigʻuvchi = Yigʻuvchi(m)
for i in range(6):
yigʻuvchi.olch(20 + i * 0.75)
yigʻuvchi.yuborish()
print(f" {nom:22} {len(yigʻuvchi.yozilgan)} paket, birinchisi: {yigʻuvchi.yozilgan[0][1][:44]}")
print("\n=== 3. Qaysi qismlar ko'chuvchan emas ===")
tekshiruvlar = [
("sys.getsizeof bilan bufer hajmi", hasattr(sys, "getsizeof")),
("threading bilan fon yuborish", _import_mumkinmi("threading")),
("sqlite3 bilan saqlash", _import_mumkinmi("sqlite3")),
("f-string va dataclass", sys.version_info >= (3, 7)),
]
for tavsif, mavjud in tekshiruvlar:
holat = "bor" if mavjud else "yoq"
print(f" {tavsif:34} CPython muhitida {holat}; cheklangan muhitda muqobil kerak")Natijaning muhim qismi:
=== 1. Muhitlar ===
CPython (haqiqiy) json=json xotira_olchovi=True iplar=True saqlash=sqlite3
MicroPython (taqlid) json=ujson xotira_olchovi=False iplar=False saqlash=fayl
Pyodide (taqlid) json=json xotira_olchovi=True iplar=False saqlash=fayl
Minimal port (taqlid) json=yo'q xotira_olchovi=False iplar=False saqlash=fayl
=== 2. Bir xil kod, to'rt muhit ===
CPython (haqiqiy) 2 paket, birinchisi: {"qiymatlar": [20.0, 20.75, 21.5, 22.25]}
MicroPython (taqlid) 2 paket, birinchisi: {"qiymatlar": [20.0, 20.75, 21.5, 22.25]}
Pyodide (taqlid) 2 paket, birinchisi: {"qiymatlar": [20.0, 20.75, 21.5, 22.25]}
Minimal port (taqlid) 2 paket, birinchisi: 20.0|20.75|21.5|22.25
=== 3. Qaysi qismlar ko'chuvchan emas ===
sys.getsizeof bilan bufer hajmi CPython muhitida bor; cheklangan muhitda muqobil kerak
threading bilan fon yuborish CPython muhitida bor; cheklangan muhitda muqobil kerak
sqlite3 bilan saqlash CPython muhitida bor; cheklangan muhitda muqobil kerak
f-string va dataclass CPython muhitida bor; cheklangan muhitda muqobil kerakNima ko'rsatdi: 2.5, 2.6-bo'limlar — muhitni bir joyda aniqlab, qolgan kodni o'zgarishsiz qoldirish mumkin.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
| "Python = CPython" | Python — spetsifikatsiya; CPython — bitta implementatsiya |
| "PyPy hamma kodni tezlashtiradi" | Sof Python sikllarda; C kengaytmalarda sekinlashtirishi mumkin |
| "PyPy'da GIL yo'q" | Bor |
| "MicroPython — kichikroq CPython" | Boshqa implementatsiya: kutubxona va turlar cheklangan |
| "Kodim ko'chuvchan, chunki faqat standart kutubxona" | __del__, is, getsizeof kabi farazlar ko'chmaydi |
"sys.implementation.name tekshiruvi yetarli" |
Imkoniyatni tekshirish ishonchliroq |
| "Pyodide — sekin o'yinchoq" | Brauzerda to'liq ilmiy stek ishlaydi |
| "Cython va PyPy — bir xil yechim" | Cython — kompilyator, PyPy — alohida interpretator |
6. Keng tarqalgan xatolar va yechimlari
1. Faylni __del__ ga ishonib yopish
def oqi(yol):
return open(yol).read() # ❌ PyPy'da deskriptor ochiq qoladi
with open(yol) as f:
return f.read() # ✅2. sys.getrefcount ga tayangan mantiq
if sys.getrefcount(obj) == 2: # ❌ boshqa implementatsiyada yo'q
if havola() is None: # ✅ weakref3. is bilan qiymat taqqoslash
if javob is "ha": # ❌
if javob == "ha": # ✅4. GIL atomarligiga tayanish
self.hisob += 1 # ❌ boshqa implementatsiyada va erkin ipli yig'mada
with self.qulf:
self.hisob += 1 # ✅5. PyPy'ni qisqa skriptlarda sinash
pypy skript.py # ⚠️ isitish ulgurmaydi — noto'g'ri xulosaReal yuk bilan, uzoq ishlaydigan rejimda o'lchang.
6. MicroPython uchun katta kutubxonalarni import qilish
import pandas as pd # ❌ mikrokontrollerda yo'q Oddiy tuzilmalar va array; og'ir hisobni serverga yuboring.
7. C kengaytmalarni PyPy'da "shunchaki ishlatish"
# ⚠️ cpyext orqali ishlaydi, lekin sekin — muqobil sof Python kutubxona qidiring8. id() ni manzil deb hisoblash
korsatkich = id(obj) # ❌ faqat CPython'da manzil7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 11.2-dars (o'tilgan):
isva== - 11.4-dars (o'tilgan):
__del__va resurslarni yopish - 11.7-dars (o'tilgan): interning — implementatsiya tafsiloti
- 12.4-dars (o'tilgan): C API va kengaytmalar
- 12.5–12.6-darslar (o'tilgan): GIL va strategiyalar
- 12.8-dars: CPython 3.11+ tezlik yaxshilanishlari — JIT g'oyalari
- 17-qism: testlarni bir nechta muhitda o'tkazish
- 19-qism: paketlash: wheel,
abi3, PyPy uchun paketlar - 26-qism: IoT va avtomatlashtirish — MicroPython
- 30-qism: Cython, Nuitka, boshqa tillar bilan integratsiya
8. Eng yaxshi amaliyotlar
Spetsifikatsiyaga tayaning, implementatsiya tafsilotlariga emas.
Resurslarni
withyoki aniqclose()bilan yoping.Imkoniyatni tekshiring (
hasattr,try/import), nomni emas.Umumiy holatni qulf bilan himoyalang.
PyPy ni real yuk bilan o'lchang — qisqa test aldaydi.
Mikrokontroller kodida xotira ajratishni kamaytiring.
CI da bir nechta implementatsiyani sinang (kutubxona yozayotgan bo'lsangiz).
Implementatsiyaga bog'liq qismlarni bitta joyda saqlang (moslashuv qatlami).
9. Amaliy topshiriq
Vazifa 1: Natijani bashorat qiling
import sys
import platform
1. print(sys.implementation.name)
2. print(platform.python_implementation())
3. print(sys.implementation.name == platform.python_implementation().lower())
4. print(hasattr(sys, "getrefcount"))
5. print(sys.implementation.cache_tag.startswith("cpython"))
6. print(type(sys.implementation.version).__name__)
7. print(sys.version_info >= (3, 11))
8. try:
import ujson
print("ujson")
except ImportError:
print("json")
9. print(hasattr(sys, "_getframe"), hasattr(sys, "getsizeof"))
10. class K:
pass
k = K()
print(id(k) == id(k))
11. import gc
print(gc.isenabled())
12. print("pypy" in sys.version.lower())Javoblar
cpythonCPythonTrueTrueTruesys.version_infoturi —version_infoTruejson—ujsonodatda o'rnatilmaganTrue TrueTrueTrueFalse
Vazifa 2: Xatolarni tuzating
1. class Ulanish:
def __init__(self, manzil):
self.s = ochish(manzil)
def __del__(self):
self.s.close()
2. def sozlama():
matn = open("sozlama.json").read()
return json.loads(matn)
3. def implementatsiya_tekshir():
if sys.implementation.name != "cpython":
raise RuntimeError("faqat CPython")
return sys.getsizeof(KESH)
4. def kutubxona_yukla():
import numpy as np
return np.zeros(1000) # MicroPython uchun ham mo'ljallangan modul
5. hisoblagich = 0
def oshir():
global hisoblagich
hisoblagich += 1 # ko'p ipli xizmatJavoblar
1. class Ulanish:
def __init__(self, manzil):
self.s = ochish(manzil)
self._fin = weakref.finalize(self, self.s.close) # zaxira
def yop(self):
self._fin()
def __enter__(self):
return self
def __exit__(self, *xato):
self.yop()
2. def sozlama():
with open("sozlama.json") as f: # aniq yopish
return json.load(f)
3. def kesh_hajmi(kesh):
if hasattr(sys, "getsizeof"): # imkoniyat bo'yicha
return sys.getsizeof(kesh)
return len(kesh) # taxminiy muqobil
4. def kutubxona_yukla(uzunlik=1000):
try:
import numpy as np
return np.zeros(uzunlik)
except ImportError:
from array import array
return array("f", bytes(4 * uzunlik)) # cheklangan muhitda
5. import threading
_qulf = threading.Lock()
hisoblagich = 0
def oshir():
global hisoblagich
with _qulf:
hisoblagich += 1Vazifa 3: PyPy bilan tajriba
- PyPy ni o'rnating (
pypyyokiuv python install pypy@3.11) - Uchta yukni CPython va PyPy da o'lchang: sof Python sikl,
jsonbilan ishlash,hashlibbilan xeshlash - Har biri uchun isitish ta'sirini ko'rsating: birinchi 1 soniya va keyingi 10 soniya
- Natijalarni jadvalda ko'rsatib, qaysi yuk uchun PyPy mos kelishini tushuntiring
- Xotira sarfini ham solishtiring
Vazifa 4: Ko'chuvchanlik tekshiruvchisini kengaytirish
Misol 3 dagi vositani rivojlantiring:
- Butun papkani (rekursiv) tekshirsin,
# noqa: portabilityizohini hurmat qilsin - Yangi qoidalar:
time.clock,os.fork,signalga bog'liqlik,sys.setrecursionlimit - Har topilma uchun tuzatish namunasini (
fix-it) chiqarsin - JSON va matn hisobot formatlarini qo'llab-quvvatlasin, xatolar bo'lsa chiqish kodi 1 bo'lsin
- O'z loyihangizga qo'llab, natijalarni tahlil qiling
Vazifa 5: MicroPython uchun qayta yozish
Server uchun yozilgan sensor modulini mikrokontroller uchun moslang:
dataclassvatypingni oddiy sinf va izohlar bilan almashtiringjson.dumpso'rniga oldindan ajratilganbytearrayga yozadigan formatter yozing- Xotira ajratishlar sonini
tracemallocbilan (CPython'da) o'lchab, kamaytiring - Ikkala variant bir xil natija berishini testlar bilan tasdiqlang
Vazifa 6: Pyodide
- Oddiy hisob-kitob funksiyasini yozing va uni Pyodide (brauzer) da ishga tushiring
- JavaScript'dan Python funksiyasini chaqirib, natijani sahifada ko'rsating
- Fayl tizimi va tarmoq cheklovlarini hujjatlashtiring
- CPython va Pyodide dagi bir xil hisobning vaqtini solishtiring
Vazifa 7: O'ylash
JavaScript'da bir nechta dvigatel bor (V8, SpiderMonkey, JavaScriptCore) va ular bitta standart (ECMAScript) ga bo'ysunadi; Java'da JVM spetsifikatsiyasi va ko'plab implementatsiyalar mavjud; C da esa standart va o'nlab kompilyatorlar. Python'da spetsifikatsiya rasmiy standart emas — "CPython nima qilsa, shu". Bu yondashuvning afzalliklari va kamchiliklari nimada, va PyPy kabi implementatsiyalar uchun bu nimani anglatadi?
Javob
Qisqa javob: Python'da til hujjat va CPython manba kodi bilan belgilanadi; rasmiy standartlashtirish organi yo'q. Bu tez rivojlanishga imkon beradi, lekin boshqa implementatsiyalarni CPython ortidan quvishga majbur qiladi va "implementatsiya tafsiloti" bilan "til qoidasi" chegarasini xiralashtiradi.
1. Modellar
| Ekotizim | Standart | Implementatsiyalar |
|---|---|---|
| JavaScript | ECMAScript (TC39, yillik relizlar) | V8, SpiderMonkey, JavaScriptCore |
| Java | JLS + JVM spetsifikatsiyasi, TCK testlari | HotSpot, OpenJ9, GraalVM |
| C / C++ | ISO standarti | GCC, Clang, MSVC |
| Python | Til hujjati + PEP lar + CPython amaliyoti | CPython, PyPy, MicroPython, GraalPy |
2. Afzalliklari
- Tezkorlik: yangi xususiyat PEP va CPython implementatsiyasi bilan bir yilda yetib keladi (match, TaskGroup, PEP 649)
- Aniqlik: noaniq joyda "CPython qanday qiladi" degan javob bor
- Kam byurokratiya: kichik jamoa qaror qabul qiladi
3. Kamchiliklari
- Boshqa implementatsiyalar ortda: PyPy 3.11 ni qo'llab-quvvatlaganda CPython 3.14 chiqadi
- Chegara xiralashgan: ko'p kod "tasodifiy" CPython xulqiga tayanadi (refcount, interning)
- C API — yashirin standart: kengaytmalar CPython ichki tuzilishiga bog'lanadi; PyPy
cpyextni taqlid qilishga majbur - Rasmiy muvofiqlik testi yo'q: "Python-mos" degani aniq o'lchanmaydi (CPython test to'plami norasmiy mezon)
4. PyPy uchun bu nimani anglatadi
- CPython test to'plamini va real kutubxonalarni ishlatib moslikni tekshiradi
- Ichki xulqlarni (masalan,
sys.getsizeof,id()) o'z modeliga moslab, ba'zan umuman qo'llab-quvvatlamaydi - C kengaytmalar uchun
cpyext— sekin va murakkab qatlam; shuning uchun sof Python kutubxonalar afzal - Har CPython relizidan keyin yangi xususiyatlarni qayta implementatsiya qilish kerak
5. Yaxshilanish yo'nalishlari
- Stable ABI / Limited API 12.4-bob — kengaytmalarni ichki tuzilishdan ajratadi
- HPy loyihasi — implementatsiyaga bog'liq bo'lmagan kengaytma API si
- PEP larda "implementatsiya tafsiloti" ni aniq belgilash amaliyoti kuchaymoqda
6. Xulosa
- Python'da rasmiy standart yo'q — til CPython va hujjatlar bilan belgilanadi
- Bu tezkor rivojlanish beradi, lekin alternativ implementatsiyalarni qiyin ahvolga soladi
- Dasturchi uchun xulosa: hujjatda kafolatlangan xulqqa tayaning, "CPython'da ishlayapti" ga emas
- HPy va Stable ABI kabi tashabbuslar ekotizimni implementatsiyadan mustaqilroq qiladi
Nimani mustahkamlaydi: 2.1–2.7-bo'limlar.
Xulosa
Bu darsda Python implementatsiyalari dunyosini ko'rib chiqdik.
Eng muhim uch fikr:
Python — til, CPython — implementatsiya. PyPy izli JIT bilan uzoq ishlaydigan sof Python kodni bir necha barobar tezlashtiradi (lekin isitish kerak va C kengaytmalar sekin), MicroPython bir necha yuz kilobayt xotirada ishlaydi (kutubxonaning kichik qismi bilan), GraalPy JVM ekotizimiga, Pyodide esa brauzerga olib chiqadi. Cython va Nuitka — interpretator emas, kompilyatorlar.
CPython'ga xos farazlar ko'chmaydi. Oxirgi havola ketishi bilan obyektning o'chishi (va shu bilan faylning yopilishi),
id()ning manzil bo'lishi, satrlar interningi,list.appendning atomarligi,sys.getrefcountvactypes— hammasi implementatsiya tafsiloti. Ko'chuvchan kodwith/finalize,==, qulflar vaweakrefga tayanadi.Imkoniyatni tekshiring, nomni emas.
sys.implementation.namefaqat ma'lumot uchun; haqiqiy qarorhasattrvatry/importbilan qabul qilinadi. Implementatsiyaga bog'liq qismlarni bitta moslashuv qatlamida saqlang — shunda bitta kod server, mikrokontroller va brauzerda ishlay oladi.
Keyingi darsda CPython'ning o'zi qanday tezlashayotganini ko'ramiz: 3.11 dagi ixtisoslashgan adaptiv interpretator, arzon freymlar, nol narxli istisnolar va 3.13+ dagi tajribaviy JIT.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!