Mundarija (21)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Konveyer
- 2.2. Ko'rinish sohalari kompilyatsiyada aniqlanadi
- 2.3. Kompilyatsiya xatosi va ish vaqti xatosi
- 2.4. Kod obyekti
- 2.5. .pyc fayllar
- 2.6. Optimallashtirish darajalari
- 2.7. Virtual mashina
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Konveyer bosqichlari
- Misol 2 — Kod obyekti anatomiyasi
- Misol 3 — .pyc ichidan
- Misol 4 — Amaliy: formulalar dvigateli
- 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.1-dars: Kod qanday bajariladi: manba → bytecode → VM
12-QISM — CPYTHON ICHKI TUZILISHI · 1-dars
1. Kirish va motivatsiya
11-qismda obyektlar xotirada qanday yashashini ko'rdik. Endi savol: python app.py buyrug'idan keyin kodning o'zi bilan nima sodir bo'ladi?
Real vaziyat. Jamoa FastAPI servisini Kubernetes'ga joylashtirdi. Xavfsizlik talabi bilan konteyner fayl tizimi faqat o'qish rejimida. Har pod ishga tushishi 4 soniyadan 11 soniyaga oshdi, avtomatik masshtablash yuk cho'qqisida ulgurmay qoldi. Sabab: Python har import qilingan modulni qayta kompilyatsiya qilayotgan edi — kompilyatsiya natijasini (__pycache__/*.pyc) diskka yoza olmagani uchun keyingi ishga tushishda ham qayta kompilyatsiya qildi. Yechim — Docker obrazini yig'ish bosqichida python -m compileall bitta qatori. Ishga tushish 3 soniyaga tushdi.
Bu muammoni ko'rish uchun "Python — interpretator, u kodni qatorma-qator o'qiydi" degan tasavvur yetmaydi. Aslida CPython avval butun faylni kompilyator kabi tahlil qiladi va bayt-kodga aylantiradi, keyin bu bayt-kodni o'z virtual mashinasida bajaradi.
Bu darsda:
- Konveyer: manba → tokenlar → AST → ko'rinish sohalari jadvali → bayt-kod → VM
- Har bosqichni standart kutubxona bilan ko'rish:
tokenize,ast,symtable,compile,dis - Kod obyekti (
code): nimalardan iborat - Kompilyatsiya xatolari va ish vaqti xatolari farqi
-
.pycfayllar: sarlavha, bekor qilish usullari,compileall - Optimallashtirish darajalari:
-O,-OO - Amaliy: formulalarni bir marta kompilyatsiya qilib, ko'p marta bajarish
2. Nazariya — chuqur tushuntirish
2.1. Konveyer
app.py (baytlar)
│ 1. Dekodlash — UTF-8 (yoki # -*- coding -*-)
▼
matn
│ 2. Tokenizator — NAME, OP, NUMBER, NEWLINE, INDENT ...
▼
tokenlar
│ 3. Parser (PEG) — grammatika bo'yicha daraxt
▼
AST (abstrakt sintaksis daraxti)
│ 4. Symtable — har nom: local, global, free, cell
▼
AST + ko'rinish sohalari
│ 5. Kompilyator — boshqaruv oqimi grafi → optimallashtiruvchi → bayt-kod
▼
kod obyekti (code) ← .pyc ga shu saqlanadi (marshal)
│ 6. Virtual mashina — baholash sikli (ceval), freymlar
▼
natija| Bosqich | Standart vosita | Nimani ko'rsatadi |
|---|---|---|
| Tokenlar | tokenize |
Leksik birliklar |
| AST | ast.parse, ast.dump |
Tuzilma |
| Ko'rinish sohalari | symtable |
Nom qayerga tegishli |
| Kod obyekti | compile() |
Bayt-kod, konstantalar, nomlar |
| Bayt-kod | dis |
Instruksiyalar (12.2-dars) |
| Bajarish | exec(), eval() |
Natija |
Asosiy xulosa: butun modul bajarilishdan oldin kompilyatsiya qilinadi. Shuning uchun fayl oxiridagi sintaksis xatosi birinchi qatorni ham bajartirmaydi.
2.2. Ko'rinish sohalari kompilyatsiyada aniqlanadi
symtable bosqichi har bir nom uchun qaror qabul qiladi — bu ish vaqtida emas:
def tashqi():
x = 1
def ichki():
return x + y # x — free (closure, 10.12-dars), y — global
return ichki| Nom | tashqi da |
ichki da |
|---|---|---|
x |
local (cell) | free |
y |
— | global |
ichki |
local | — |
Shuning uchun 7-qismdagi UnboundLocalError paydo bo'ladi: funksiyada nomga qayerdadir qiymat berilsa, kompilyator uni butun funksiya uchun local deb belgilaydi.
Python 3.14 da symtable da __annotate__ sohalari ham ko'rinadi — annotatsiyalar dangasa hisoblanadi (PEP 649).
2.3. Kompilyatsiya xatosi va ish vaqti xatosi
| Xato | Qachon | Misol |
|---|---|---|
SyntaxError, IndentationError |
Kompilyatsiyada — hech narsa bajarilmaydi | def f(: |
| Ba'zi semantik xatolar | Kompilyatsiyada (symtable) | nonlocal x modul darajasida, return funksiyadan tashqarida |
NameError, TypeError, ... |
Ish vaqtida, shu qatorga yetib kelganda | print(yoq_ozgaruvchi) |
compile("print(yoq_ozgaruvchi)", ...) muvaffaqiyatli o'tadi — kompilyator nom mavjudligini tekshirmaydi, faqat qanday qidirishni (global) belgilaydi.
2.4. Kod obyekti
compile() va har bir def, lambda, class tanasi, comprehension — kod obyekti hosil qiladi. U o'zgarmas:
| Atribut | Ma'nosi |
|---|---|
co_code |
Bayt-kod (baytlar) |
co_consts |
Konstantalar: sonlar, satrlar, ichki kod obyektlari |
co_names |
Global va atribut nomlari |
co_varnames |
Lokal o'zgaruvchilar (parametrlar birinchi) |
co_cellvars, co_freevars |
Closure hujayralari (10.12-dars) |
co_argcount, co_kwonlyargcount, co_posonlyargcount |
Parametrlar soni |
co_stacksize |
Kerakli stek chuqurligi |
co_flags |
Generator, korutina, *args va h.k. bayroqlari |
co_filename, co_name, co_qualname, co_firstlineno |
Joylashuv |
co_lines(), co_positions() |
Bayt-kod ↔ manba qator va ustunlar |
Funksiya ≠ kod obyekti. Funksiya = kod obyekti + __globals__ + __defaults__ + __closure__ + nom (11.6-dars). Bitta kod obyektidan ko'p funksiya yaratilishi mumkin (sikldagi def).
code.replace(...) — o'zgartirilgan nusxa (debugger, profiler va test vositalari ishlatadi).
2.5. .pyc fayllar
Qachon yoziladi: modul import qilinganda — __pycache__/modul.cpython-314.pyc. Asosiy skript (python app.py) uchun .pyc yozilmaydi.
Sarlavha (16 bayt):
| Bayt | Maydon |
|---|---|
| 0–3 | Magic raqam — Python versiyasi (importlib.util.MAGIC_NUMBER) |
| 4–7 | Bayroqlar: 0 — vaqt belgisi; 1 — xesh; 3 — xesh + manbani tekshirish |
| 8–15 | Vaqt belgisi rejimi: manba mtime va hajmi; xesh rejimi: manba xeshi (8 bayt) |
| 16– | marshal qilingan kod obyekti |
Bekor qilish (invalidation) usullari:
| Rejim | Qanday tekshiriladi | Qayerda |
|---|---|---|
TIMESTAMP (sukut) |
Manba mtime va hajmi sarlavhadagiga tengmi |
Oddiy ishlab chiqish |
CHECKED_HASH |
Manba xeshi hisoblanib solishtiriladi | Qayta tiklanadigan (reproducible) yig'malar |
UNCHECKED_HASH |
Tekshirilmaydi | Tizim paketlari, o'zgarmas obrazlar |
Magic raqam mos kelmasa (boshqa Python versiyasi) — .pyc e'tiborsiz qoldiriladi va qayta kompilyatsiya qilinadi.
Boshqaruv:
| Vosita | Ta'siri |
|---|---|
python -m compileall papka |
Hammasini oldindan kompilyatsiya qilish |
python -B, PYTHONDONTWRITEBYTECODE=1 |
.pyc yozmaslik |
PYTHONPYCACHEPREFIX=/tmp/pyc |
Keshni boshqa papkada saqlash (faqat o'qish tizimlari uchun) |
2.6. Optimallashtirish darajalari
| Bayroq | sys.flags.optimize |
Nima olib tashlanadi | .pyc nomi |
|---|---|---|---|
| — | 0 | Hech narsa | modul.cpython-314.pyc |
-O |
1 | assert va if __debug__: bloklari |
.opt-1.pyc |
-OO |
2 | Yuqoridagilar + docstringlar | .opt-2.pyc |
assert ni foydalanuvchi ma'lumotini tekshirish uchun ishlatmang — -O bilan u yo'qoladi (9-qism).
2.7. Virtual mashina
CPython VM — stek mashinasi: har instruksiya qiymatlar stekidan oladi va unga qo'yadi.
narx * soni LOAD_FAST narx stek: [narx]
LOAD_FAST soni stek: [narx, soni]
BINARY_OP * stek: [natija](Soddalashtirilgan: 3.14 da dis birlashtirilgan instruksiyalarni ko'rsatadi, masalan LOAD_FAST_BORROW_LOAD_FAST_BORROW — 12.2-dars.)
- Har funksiya chaqiruvi — yangi freym (lokal o'zgaruvchilar, stek, joriy instruksiya) — 12.3-dars
- Baholash sikli (
ceval.c) instruksiyalarni ketma-ket bajaradi - 3.11+ da instruksiyalar ish vaqtida ixtisoslashadi (
BINARY_OP→BINARY_OP_MULTIPLY_FLOAT) — 12.8-dars - 3.13+ da tajribaviy JIT kompilyator mavjud (sukut bo'yicha o'chiq)
compile rejimlari:
| Rejim | Kirish | Natija |
|---|---|---|
"exec" |
Modul (ko'p statement) | exec() — None |
"eval" |
Bitta ifoda | eval() — qiymat |
"single" |
Bitta interaktiv statement | REPL kabi: ifoda qiymati chop etiladi |
3. Tez ma'lumotnoma
Bosqichlarni ko'rish
tokenize.generate_tokens(io.StringIO(src).readline)
ast.dump(ast.parse(src), indent=2)
symtable.symtable(src, "<nom>", "exec")
code = compile(src, "<nom>", "exec" | "eval" | "single", optimize=-1|0|1|2)
dis.dis(code) exec(code, globals_dict)Kod obyekti
co_code co_consts co_names co_varnames co_freevars co_cellvars
co_argcount co_stacksize co_flags co_qualname co_firstlineno
co_lines() co_positions() code.replace(...).pyc
__pycache__/modul.cpython-314[.opt-N].pyc
sarlavha 16 bayt: magic | bayroqlar | mtime+hajm yoki xesh
python -m compileall [--invalidation-mode checked-hash] papka
-B / PYTHONDONTWRITEBYTECODE PYTHONPYCACHEPREFIX4. Batafsil misollar
Misol 1 — Konveyer bosqichlari
"""Bitta manba: tokenlar, AST, symtable ko'rinish sohalari, kod obyekti va bajarish."""
import ast
import io
import symtable
import tokenize
MANBA = '''NARX = 12_000
def hisobla(soni, chegirma=0.1):
"""Buyurtma summasi."""
def yakuniy(qiymat):
return qiymat * (1 - chegirma)
return yakuniy(soni * NARX)
natija = hisobla(3)
'''
print("=== 1. Tokenlar ===")
tokenlar = list(tokenize.generate_tokens(io.StringIO(MANBA).readline))
print(f" jami: {len(tokenlar)}")
for t in tokenlar[:9]:
print(f" {tokenize.tok_name[t.type]:8} {t.string!r:12} qator {t.start[0]}, ustun {t.start[1]}")
turlar = {}
for t in tokenlar:
turlar[tokenize.tok_name[t.type]] = turlar.get(tokenize.tok_name[t.type], 0) + 1
print(f" turlar bo'yicha: {dict(sorted(turlar.items()))}")
print("\n=== 2. AST ===")
daraxt = ast.parse(MANBA)
print(f" modul tanasi: {[type(n).__name__ for n in daraxt.body]}")
print(f" birinchi statement: {ast.dump(daraxt.body[0])}")
funksiya = daraxt.body[1]
print(f" hisobla: parametrlar {[a.arg for a in funksiya.args.args]}, sukut {[ast.unparse(d) for d in funksiya.args.defaults]}")
print(f" return ifodasi: {ast.dump(funksiya.body[-1].value)}")
print(f" ast.unparse — daraxtdan qayta manba: {ast.unparse(funksiya.body[-1])}")
print("\n=== 3. Symtable: nom qayerga tegishli ===")
def turi(belgi):
if belgi.is_free():
return "free"
if belgi.is_parameter():
return "parametr"
if belgi.is_global():
return "global"
if belgi.is_local():
return "local"
return "?"
def aylan(jadval, chuqurlik=0):
if jadval.get_type() == symtable.SymbolTableType.ANNOTATION:
return
belgilar = ", ".join(f"{b.get_name()}:{turi(b)}" for b in jadval.get_symbols())
print(f" {' ' * chuqurlik}{jadval.get_type().value} {jadval.get_name()!r}: {belgilar}")
for bola in jadval.get_children():
aylan(bola, chuqurlik + 1)
aylan(symtable.symtable(MANBA, "<buyurtma>", "exec"))
print("\n=== 4. Kod obyekti va bajarish ===")
kod = compile(MANBA, "<buyurtma>", "exec")
print(f" turi: {type(kod).__name__}, co_names: {kod.co_names}")
print(f" konstantalar: {[f'<kod {c.co_name}>' if hasattr(c, 'co_code') else c for c in kod.co_consts]}")
muhit = {}
exec(kod, muhit)
print(f" exec dan keyin natija = {muhit['natija']}, hisobla.__code__ is ichki kod obyekti: "
f"{muhit['hisobla'].__code__ is next(c for c in kod.co_consts if hasattr(c, 'co_code'))}")
print("\n=== 5. Kompilyatsiya va ish vaqti xatolari ===")
buzuq = "print('birinchi qator bajariladimi?')\ndef f(:\n pass\n"
try:
compile(buzuq, "<buzuq>", "exec")
except SyntaxError as xato:
print(f" SyntaxError: {xato.msg}, qator {xato.lineno} — birinchi qator ham bajarilmadi")
kod = compile("print(yoq_ozgaruvchi)", "<nom>", "exec")
print(f" mavjud bo'lmagan nom kompilyatsiyadan o'tdi: co_names = {kod.co_names}")
try:
exec(kod, {})
except NameError as xato:
print(f" ish vaqtida: NameError: {xato}")
try:
compile("def f():\n x = 1\n global x\n", "<nom>", "exec")
except SyntaxError as xato:
print(f" symtable bosqichidagi xato: {xato.msg}")Natijaning muhim qismi:
=== 1. Tokenlar ===
jami: 55
NAME 'NARX' qator 1, ustun 0
OP '=' qator 1, ustun 5
NUMBER '12_000' qator 1, ustun 7
NEWLINE '\n' qator 1, ustun 13
NL '\n' qator 2, ustun 0
NAME 'def' qator 3, ustun 0
NAME 'hisobla' qator 3, ustun 4
OP '(' qator 3, ustun 11
NAME 'soni' qator 3, ustun 12
turlar bo'yicha: {'DEDENT': 2, 'ENDMARKER': 1, 'INDENT': 2, 'NAME': 17, 'NEWLINE': 7, 'NL': 2, 'NUMBER': 4, 'OP': 19, 'STRING': 1}
=== 2. AST ===
modul tanasi: ['Assign', 'FunctionDef', 'Assign']
birinchi statement: Assign(targets=[Name(id='NARX', ctx=Store())], value=Constant(value=12000))
hisobla: parametrlar ['soni', 'chegirma'], sukut ['0.1']
return ifodasi: Call(func=Name(id='yakuniy', ctx=Load()), args=[BinOp(left=Name(id='soni', ctx=Load()), op=Mult(), right=Name(id='NARX', ctx=Load()))])
ast.unparse — daraxtdan qayta manba: return yakuniy(soni * NARX)
=== 3. Symtable: nom qayerga tegishli ===
module 'top': NARX:global, hisobla:global, natija:global
function 'hisobla': soni:parametr, chegirma:parametr, yakuniy:local, NARX:global
function 'yakuniy': qiymat:parametr, chegirma:free
=== 4. Kod obyekti va bajarish ===
turi: code, co_names: ('NARX', 'hisobla', 'natija')
konstantalar: [12000, '<kod hisobla>', None, (0.1,)]
exec dan keyin natija = 32400.0, hisobla.__code__ is ichki kod obyekti: True
=== 5. Kompilyatsiya va ish vaqti xatolari ===
SyntaxError: invalid syntax, qator 2 — birinchi qator ham bajarilmadi
mavjud bo'lmagan nom kompilyatsiyadan o'tdi: co_names = ('print', 'yoq_ozgaruvchi')
ish vaqtida: NameError: name 'yoq_ozgaruvchi' is not defined
symtable bosqichidagi xato: name 'x' is assigned to before global declarationNima ko'rsatdi: 2.1–2.3-bo'limlar.
Misol 2 — Kod obyekti anatomiyasi
"""Kod obyekti atributlari; funksiya va kod obyekti farqi; co_lines; code.replace; compile rejimlari va optimize darajalari."""
import dis
def buyurtma_summasi(narx, soni, *, chegirma=0.0):
"""Chegirmali summa."""
assert soni > 0, "soni musbat bo'lsin"
oraliq = narx * soni
return round(oraliq * (1 - chegirma), 2)
kod = buyurtma_summasi.__code__
print("=== 1. Atributlar ===")
for nom in ["co_name", "co_qualname", "co_argcount", "co_kwonlyargcount", "co_varnames",
"co_names", "co_consts", "co_stacksize", "co_firstlineno"]:
print(f" {nom:18} {getattr(kod, nom)!r}")
bayroqlar = [nom for bit, nom in dis.COMPILER_FLAG_NAMES.items() if kod.co_flags & bit]
print(f" {'co_flags':18} {bayroqlar}")
print(f" {'len(co_code)':18} {len(kod.co_code)} bayt")
print("\n=== 2. Bayt-kod ↔ qatorlar ===")
for bosh, oxir, qator in kod.co_lines():
if qator is not None:
print(f" baytlar {bosh:>3}–{oxir:<3} → qator +{qator - kod.co_firstlineno}")
print("\n=== 3. Funksiya ≠ kod obyekti ===")
yaratilgan = []
for foiz in (5, 10):
def chegirma(summa, foiz=foiz):
return summa * (100 - foiz) / 100
yaratilgan.append(chegirma)
print(f" ikki funksiya bitta obyektmi: {yaratilgan[0] is yaratilgan[1]}, kodi bitta obyektmi: {yaratilgan[0].__code__ is yaratilgan[1].__code__}")
print(f" farq faqat __defaults__ da: {yaratilgan[0].__defaults__}, {yaratilgan[1].__defaults__}")
nusxa = type(buyurtma_summasi)(kod, {"round": round}, "nusxa")
try:
nusxa(100, 3)
except TypeError as xato:
print(f" kod obyektidan yangi funksiya, sukutlarsiz: TypeError: {xato}")
print(f" sukutlar funksiyada, kodda emas: __kwdefaults__ {buyurtma_summasi.__kwdefaults__} va {nusxa.__kwdefaults__}")
print(f" chegirma berilsa: {nusxa.__name__}(100, 3, chegirma=0.1) = {nusxa(100, 3, chegirma=0.1)}")
print("\n=== 4. code.replace ===")
def salomlash():
return "Assalomu alaykum"
eski = salomlash.__code__
salomlash.__code__ = eski.replace(co_consts=tuple("Xush kelibsiz" if c == "Assalomu alaykum" else c for c in eski.co_consts))
print(f" konstanta almashtirildi: {salomlash()}")
salomlash.__code__ = eski
print("\n=== 5. compile rejimlari ===")
print(f" eval: {eval(compile('2 ** 10 + 24', '<e>', 'eval'))}")
muhit = {}
print(f" exec: {exec(compile('x = 2 ** 10', '<x>', 'exec'), muhit)}, x = {muhit['x']}")
print(" single (REPL kabi, ifoda qiymatini o'zi chop etadi):")
exec(compile("2 ** 10 + 24", "<s>", "single"))
try:
compile("x = 1", "<e>", "eval")
except SyntaxError as xato:
print(f" eval rejimida statement: SyntaxError: {xato.msg}")
print("\n=== 6. optimize darajalari ===")
MANBA = '''def f(soni):
"""Hujjat satri."""
assert soni > 0
if __debug__:
tekshiruv = "debug"
return soni
'''
for daraja in (0, 1, 2):
muhit = {}
exec(compile(MANBA, "<opt>", "exec", optimize=daraja), muhit)
f = muhit["f"]
try:
f(-1)
assert_holati = "o'chirildi"
except AssertionError:
assert_holati = "ishladi"
print(f" optimize={daraja}: bayt-kod {len(f.__code__.co_code):>2} bayt, assert {assert_holati:10}, "
f"__doc__ {f.__doc__!r}, 'debug' konstantada: {'debug' in f.__code__.co_consts}")Natijaning muhim qismi:
=== 1. Atributlar ===
co_name 'buyurtma_summasi'
co_qualname 'buyurtma_summasi'
co_argcount 2
co_kwonlyargcount 1
co_varnames ('narx', 'soni', 'chegirma', 'oraliq')
co_names ('round',)
co_consts ('Chegirmali summa.', "soni musbat bo'lsin")
co_stacksize 5
co_firstlineno 6
co_flags ['OPTIMIZED', 'NEWLOCALS', 'HAS_DOCSTRING']
len(co_code) 98 bayt
=== 2. Bayt-kod ↔ qatorlar ===
baytlar 0–2 → qator +0
baytlar 2–30 → qator +2
baytlar 30–46 → qator +3
baytlar 46–98 → qator +4
=== 3. Funksiya ≠ kod obyekti ===
ikki funksiya bitta obyektmi: False, kodi bitta obyektmi: True
farq faqat __defaults__ da: (5,), (10,)
kod obyektidan yangi funksiya, sukutlarsiz: TypeError: buyurtma_summasi() missing 1 required keyword-only argument: 'chegirma'
sukutlar funksiyada, kodda emas: __kwdefaults__ {'chegirma': 0.0} va None
chegirma berilsa: nusxa(100, 3, chegirma=0.1) = 270.0
=== 4. code.replace ===
konstanta almashtirildi: Xush kelibsiz
=== 5. compile rejimlari ===
eval: 1048
exec: None, x = 1024
single (REPL kabi, ifoda qiymatini o'zi chop etadi):
1048
eval rejimida statement: SyntaxError: invalid syntax
=== 6. optimize darajalari ===
optimize=0: bayt-kod 30 bayt, assert ishladi , __doc__ 'Hujjat satri.', 'debug' konstantada: True
optimize=1: bayt-kod 8 bayt, assert o'chirildi, __doc__ 'Hujjat satri.', 'debug' konstantada: False
optimize=2: bayt-kod 8 bayt, assert o'chirildi, __doc__ None, 'debug' konstantada: FalseNima ko'rsatdi: 2.4, 2.6, 2.7-bo'limlar.
Misol 3 — .pyc ichidan
"""py_compile bilan .pyc; 16 baytli sarlavhani o'qish; marshal bilan kod obyektini tiklash; xesh rejimi; import keshni ishlatishi."""
import importlib
import importlib.util
import marshal
import pathlib
import py_compile
import struct
import sys
import tempfile
papka = pathlib.Path(tempfile.mkdtemp())
manba = papka / "narxlar.py"
manba.write_bytes(b'KURS = 12_650\n\ndef som(dollar):\n return dollar * KURS\n\nprint("narxlar moduli bajarildi")\n')
def nisbiy(yol):
return pathlib.Path(yol).relative_to(papka).as_posix()
print("=== 1. Kesh fayl nomi ===")
print(f" cache_tag: {sys.implementation.cache_tag}")
print(f" oddiy: {nisbiy(importlib.util.cache_from_source(manba))}")
print(f" -OO: {nisbiy(importlib.util.cache_from_source(manba, optimization=2))}")
print("\n=== 2. Sarlavha (vaqt belgisi rejimi) ===")
pyc = pathlib.Path(py_compile.compile(manba, doraise=True))
baytlar = pyc.read_bytes()
magic = baytlar[:4]
bayroqlar, mtime, hajm = struct.unpack("<III", baytlar[4:16])
print(f" fayl: {nisbiy(pyc)}, jami {len(baytlar)} bayt")
print(f" magic {magic!r} == MAGIC_NUMBER: {magic == importlib.util.MAGIC_NUMBER}")
print(f" bayroqlar: {bayroqlar}, mtime mos: {mtime == int(manba.stat().st_mtime)}, hajm {hajm} == manba {manba.stat().st_size}")
print("\n=== 3. marshal: kod obyektini tiklash ===")
kod = marshal.loads(baytlar[16:])
print(f" turi: {type(kod).__name__}, co_names: {kod.co_names}")
muhit = {"__name__": "narxlar"}
exec(kod, muhit)
print(f" manbasiz bajarildi: som(3) = {muhit['som'](3):,}")
print("\n=== 4. Xesh rejimi ===")
pyc = pathlib.Path(py_compile.compile(manba, doraise=True, invalidation_mode=py_compile.PycInvalidationMode.CHECKED_HASH))
baytlar = pyc.read_bytes()
bayroqlar = struct.unpack("<I", baytlar[4:8])[0]
print(f" bayroqlar: {bayroqlar} (xesh: {bool(bayroqlar & 1)}, manbani tekshirish: {bool(bayroqlar & 2)})")
print(f" sarlavhadagi xesh == source_hash(manba): {baytlar[8:16] == importlib.util.source_hash(manba.read_bytes())}")
print("\n=== 5. import keshni ishlatadi ===")
py_compile.compile(manba, doraise=True)
sys.path.insert(0, str(papka))
sys.dont_write_bytecode = False
import narxlar
print(f" narxlar.__cached__: {nisbiy(narxlar.__cached__)}")
pyc_yol = pathlib.Path(narxlar.__cached__)
oldingi = pyc_yol.stat().st_mtime_ns
del sys.modules["narxlar"]
importlib.import_module("narxlar")
print(f" qayta import: .pyc qayta yozilmadi — {pyc_yol.stat().st_mtime_ns == oldingi}")
pyc_yol.write_bytes(b"\x00\x00\x00\x00" + pyc_yol.read_bytes()[4:])
del sys.modules["narxlar"]
importlib.import_module("narxlar")
print(f" buzilgan magic: Python .pyc ni e'tiborsiz qoldirib, qayta kompilyatsiya qildi — {pyc_yol.read_bytes()[:4] == importlib.util.MAGIC_NUMBER}")
sys.path.remove(str(papka))Natijaning muhim qismi:
=== 1. Kesh fayl nomi ===
cache_tag: cpython-314
oddiy: __pycache__/narxlar.cpython-314.pyc
-OO: __pycache__/narxlar.cpython-314.opt-2.pyc
=== 2. Sarlavha (vaqt belgisi rejimi) ===
fayl: __pycache__/narxlar.cpython-314.pyc, jami 370 bayt
magic b'+\x0e\r\n' == MAGIC_NUMBER: True
bayroqlar: 0, mtime mos: True, hajm 92 == manba 92
=== 3. marshal: kod obyektini tiklash ===
turi: code, co_names: ('KURS', 'som', 'print')
narxlar moduli bajarildi
manbasiz bajarildi: som(3) = 37,950
=== 4. Xesh rejimi ===
bayroqlar: 3 (xesh: True, manbani tekshirish: True)
sarlavhadagi xesh == source_hash(manba): True
=== 5. import keshni ishlatadi ===
narxlar moduli bajarildi
narxlar.__cached__: __pycache__/narxlar.cpython-314.pyc
narxlar moduli bajarildi
qayta import: .pyc qayta yozilmadi — True
narxlar moduli bajarildi
buzilgan magic: Python .pyc ni e'tiborsiz qoldirib, qayta kompilyatsiya qildi — TrueNima ko'rsatdi: 2.5-bo'lim. Modul har importda emas, faqat birinchi va .pyc yaroqsiz bo'lganda kompilyatsiya qilinadi; "narxlar moduli bajarildi" esa har import_module da chiqdi — kompilyatsiya keshlanadi, modul kodining bajarilishi emas.
Misol 4 — Amaliy: formulalar dvigateli
Jadval ilovasida foydalanuvchi ustunlar uchun formulalar yozadi: narx * soni * (1 - chegirma). Formula har qator uchun bajariladi. Konveyerni boshqarib, uni xavfsiz va tez qilamiz: AST darajasida ruxsat etilgan tugunlarni tekshiramiz, bir marta kompilyatsiya qilamiz va kod obyektini keshlaymiz.
"""Formula: ast bilan tekshiruv (oq ro'yxat), compile bir marta, kesh; har qatorda eval bilan solishtirish; xavfli formulalarni rad etish."""
import ast
import math
import time
from functools import lru_cache
RUXSAT_TUGUNLAR = (ast.Expression, ast.BinOp, ast.UnaryOp, ast.Constant, ast.Name, ast.Load,
ast.Add, ast.Sub, ast.Mult, ast.Div, ast.Pow, ast.Mod, ast.USub, ast.UAdd,
ast.Call, ast.Compare, ast.Gt, ast.Lt, ast.GtE, ast.LtE, ast.Eq, ast.IfExp)
FUNKSIYALAR = {"round": round, "min": min, "max": max, "abs": abs, "sqrt": math.sqrt}
class FormulaXatosi(ValueError):
pass
@lru_cache(maxsize=256)
def kompilyatsiya(formula, ustunlar):
try:
daraxt = ast.parse(formula, mode="eval")
except SyntaxError as xato:
raise FormulaXatosi(f"sintaksis: {xato.msg}") from None
for tugun in ast.walk(daraxt):
if not isinstance(tugun, RUXSAT_TUGUNLAR):
raise FormulaXatosi(f"ruxsat etilmagan: {type(tugun).__name__}")
if isinstance(tugun, ast.Name) and tugun.id not in ustunlar and tugun.id not in FUNKSIYALAR:
raise FormulaXatosi(f"noma'lum nom: {tugun.id}")
if isinstance(tugun, ast.Call) and not (isinstance(tugun.func, ast.Name) and tugun.func.id in FUNKSIYALAR):
raise FormulaXatosi("faqat ruxsat etilgan funksiyalar")
return compile(daraxt, f"<formula: {formula}>", "eval")
def hisobla(formula, qatorlar):
kod = kompilyatsiya(formula, tuple(sorted(qatorlar[0])))
muhit = {"__builtins__": {}, **FUNKSIYALAR}
return [eval(kod, muhit, qator) for qator in qatorlar]
QATORLAR = [{"narx": 10_000.0 + i, "soni": i % 7, "chegirma": (i % 4) * 0.05} for i in range(30_000)]
FORMULA = "round(narx * soni * (1 - chegirma), 2)"
print("=== 1. Natija ===")
natija = hisobla(FORMULA, QATORLAR)
print(f" birinchi 4: {natija[:4]}, jami: {sum(natija):,.2f}")
print(f" kesh: {kompilyatsiya.cache_info()}")
hisobla(FORMULA, QATORLAR[:10])
print(f" ikkinchi chaqiruv: {kompilyatsiya.cache_info()}")
print("\n=== 2. Har qatorda manbadan eval va bir marta compile ===")
def har_safar(formula, qatorlar):
muhit = {"__builtins__": {}, **FUNKSIYALAR}
return [eval(formula, muhit, qator) for qator in qatorlar]
def eng_yaxshi(f, *args, takror=3):
vaqtlar = []
for _ in range(takror):
bosh = time.perf_counter()
f(*args)
vaqtlar.append(time.perf_counter() - bosh)
return min(vaqtlar)
sekin = eng_yaxshi(har_safar, FORMULA, QATORLAR)
tez = eng_yaxshi(hisobla, FORMULA, QATORLAR)
print(f" natijalar teng: {har_safar(FORMULA, QATORLAR) == natija}")
print(f" bir marta kompilyatsiya kamida 5 barobar tez: {sekin / tez > 5}")
print("\n=== 3. Xavfli va xato formulalar ===")
for yomon in ["__import__('os').system('rm -rf /')", "narx.__class__", "[x for x in range(10**9)]",
"narx * (soni", "narx * foyda", "open('parol.txt')", "soni ** 2 if soni > 3 else -soni"]:
try:
kompilyatsiya(yomon, ("chegirma", "narx", "soni"))
print(f" ✅ {yomon!r}")
except FormulaXatosi as xato:
print(f" ❌ {yomon!r}: {xato}")Natijaning muhim qismi:
=== 1. Natija ===
birinchi 4: [0.0, 9500.95, 18003.6, 25507.65], jami: 2,081,119,756.75
kesh: CacheInfo(hits=0, misses=1, maxsize=256, currsize=1)
ikkinchi chaqiruv: CacheInfo(hits=1, misses=1, maxsize=256, currsize=1)
=== 2. Har qatorda manbadan eval va bir marta compile ===
natijalar teng: True
bir marta kompilyatsiya kamida 5 barobar tez: True
=== 3. Xavfli va xato formulalar ===
❌ "__import__('os').system('rm -rf /')": faqat ruxsat etilgan funksiyalar
❌ 'narx.__class__': ruxsat etilmagan: Attribute
❌ '[x for x in range(10**9)]': ruxsat etilmagan: ListComp
❌ 'narx * (soni': sintaksis: '(' was never closed
❌ 'narx * foyda': noma'lum nom: foyda
❌ "open('parol.txt')": faqat ruxsat etilgan funksiyalar
✅ 'soni ** 2 if soni > 3 else -soni'Nima ko'rsatdi: 2.1, 2.4, 2.7-bo'limlar — konveyer bosqichlarini alohida boshqarish formulani tekshirishga (AST) va bir marta kompilyatsiya qilishga imkon beradi. AST oq ro'yxati eval ni to'liq xavfsiz qilmaydi (masalan, 10 ** 10 ** 10 kabi resurs hujumlari) — ishonchsiz kod uchun alohida jarayon va cheklovlar kerak (20-qism).
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
| "Python kodni qatorma-qator o'qib bajaradi" | Butun modul avval bayt-kodga kompilyatsiya qilinadi |
| "Python kompilyatsiya qilmaydi" | Qiladi — mashina kodiga emas, bayt-kodga |
".pyc — tezroq ishlaydigan kod" |
Bajarilish tezligi bir xil; faqat kompilyatsiya bosqichi o'tkazib yuboriladi |
"python app.py uchun ham .pyc yoziladi" |
Faqat import qilingan modullar uchun |
"NameError kompilyatsiyada topiladi" |
Ish vaqtida — kompilyator faqat qidirish usulini belgilaydi |
"-O kodni tezlashtiradi" |
Faqat assert, __debug__ va (-OO) docstringlarni olib tashlaydi |
".pyc boshqa Python versiyasida ham ishlaydi" |
Magic raqam mos kelmasa, e'tiborsiz qoldiriladi |
| "Funksiya va uning kodi — bitta narsa" | Kod obyekti o'zgarmas va ulashiladi; funksiya uni muhit bilan bog'laydi |
6. Keng tarqalgan xatolar va yechimlari
1. Faqat o'qish fayl tizimida .pyc siz ishga tushirish
COPY . /app # ⚠️ har pod ishga tushishda kompilyatsiya
RUN python -m compileall -q /app # ✅ obraz yig'ilganda2. assert bilan kiritmani tekshirish
assert summa > 0, "summa musbat bo'lsin" # ❌ -O bilan yo'qoladi
if summa <= 0:
raise ValueError("summa musbat bo'lsin") # ✅3. Sikl ichida bir xil satrni eval/exec qilish
for qator in qatorlar:
eval(formula, {}, qator) # ❌ har safar parse + compile
kod = compile(formula, "<f>", "eval")
for qator in qatorlar:
eval(kod, {}, qator) # ✅4. eval ga ishonchsiz satr berish
eval(request.args["formula"]) # ❌ istalgan kod bajariladi ast.literal_eval (faqat literallar) yoki AST oq ro'yxati + cheklangan muhit; ishonchsiz kod uchun alohida jarayon.
5. .pyc fayllarni git ga qo'shish
__pycache__/ # ✅ har doim .gitignore da
*.pyc6. Faqat .pyc tarqatib, kodni "yashirish"
python -m compileall app && rm app/*.py # ⚠️ dekompilyatorlar va dis bilan o'qiladi, versiyaga bog'liq7. Konteynerda PYTHONDONTWRITEBYTECODE=1 va yig'ishda kompilyatsiya qilmaslik
ENV PYTHONDONTWRITEBYTECODE=1 # ⚠️ o'zi yetarli emas — har ishga tushish sekin
RUN python -m compileall -q /app /usr/local/lib/python3.14 # ✅ oldindan8. Sintaksis xatosini try bilan ushlashga urinish
try:
def f(: pass # ❌ butun fayl kompilyatsiyadan o'tmaydi
except SyntaxError:
... Dinamik kod uchun compile() ni try ichida chaqiring.
7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 7-qism (o'tilgan):
UnboundLocalError— ko'rinish sohasi kompilyatsiyada aniqlanadi - 10.12-dars (o'tilgan): closure —
co_freevars,co_cellvars - 11.6-dars (o'tilgan): funksiya obyekti va
__defaults__ - 11.7-dars (o'tilgan): konstantalarni oldindan hisoblash — kompilyator optimallashtiruvchisi
- 12.2-dars:
disbilan bayt-kodni o'qish - 12.3-dars: freym va chaqiruv steki
- 12.8-dars: ixtisoslashgan adaptiv interpretator
- 19-qism: paketlash —
.pyc,compileall, wheel - 28-qism: Docker obrazlarida ishga tushish vaqtini optimallashtirish
8. Eng yaxshi amaliyotlar
Production obrazlarida
python -m compileall— ayniqsa faqat o'qish fayl tizimlarida.__pycache__va*.pyc—.gitignoreda.Dinamik kodni bir marta
compileqiling, kod obyektini qayta ishlating.Ishonchsiz ifodalar uchun AST tekshiruvi yoki
ast.literal_eval.assert— faqat dasturchi farazlari uchun.Kod tahlili vositalari uchun
ast,symtable,tokenize— regex bilan manba tahlil qilmang.Qayta tiklanadigan yig'malarda
--invalidation-mode checked-hash.Ishga tushish sekin bo'lsa,
python -X importtimebilan o'lchang (18-qism).
9. Amaliy topshiriq
Vazifa 1: Natijani bashorat qiling
import ast
1. kod = compile("1 + 2", "<t>", "eval")
print(eval(kod))
2. print(type(compile("x = 1", "<t>", "exec")).__name__)
3. try:
compile("x = 1", "<t>", "eval")
except SyntaxError:
print("SyntaxError")
4. kod = compile("print(nomalum)", "<t>", "exec")
print("kompilyatsiya bo'ldi")
5. print(type(ast.parse("a + b").body[0]).__name__)
6. print(type(ast.parse("a + b", mode="eval").body).__name__)
7. def f(a, b=2, *, c=3):
d = a + b
return d
print(f.__code__.co_argcount, f.__code__.co_kwonlyargcount)
8. print(f.__code__.co_varnames)
9. fs = [lambda: 1 for _ in range(2)]
print(fs[0] is fs[1], fs[0].__code__ is fs[1].__code__)
10. m = {}
exec(compile('def g():\n """doc"""\n return 1', "<t>", "exec", optimize=2), m)
print(m["g"].__doc__)
11. print(ast.unparse(ast.parse("x=(1+2)*3")))
12. exec(compile("5 * 5", "<t>", "single"))Javoblar
3codeSyntaxError—evalrejimi faqat ifoda qabul qiladikompilyatsiya bo'ldi— nom ish vaqtida qidiriladiExprBinOp—Expression.bodyto'g'ridan-to'g'ri ifoda2 1('a', 'b', 'c', 'd')— parametrlar birinchi, keyin lokallarFalse True— ikki funksiya, bitta kod obyektiNone—optimize=2docstringni olib tashladix = (1 + 2) * 325—singlerejimi ifoda qiymatini chop etadi
Vazifa 2: Xatolarni tuzating
1. def filtrla(yozuvlar, shart):
return [y for y in yozuvlar if eval(shart, {}, y)]
2. def yosh_tekshir(yosh):
assert 0 < yosh < 150, "noto'g'ri yosh"
return yosh
3. def sozlama_oqi(matn):
return eval(matn) # "{'port': 8080, 'debug': True}"
4. # Dockerfile
FROM python:3.14-slim
ENV PYTHONDONTWRITEBYTECODE=1
COPY app /app
CMD ["python", "-m", "app"]
5. try:
import yangi_modul
except SyntaxError:
yangi_modul = NoneJavoblar
1. def filtrla(yozuvlar, shart):
kod = compile(shart, "<shart>", "eval") # bir marta
return [y for y in yozuvlar if eval(kod, {"__builtins__": {}}, y)]
2. def yosh_tekshir(yosh):
if not 0 < yosh < 150:
raise ValueError("noto'g'ri yosh") # -O bilan yo'qolmaydi
return yosh
3. import ast
def sozlama_oqi(matn):
return ast.literal_eval(matn) # faqat literallar, kod bajarilmaydi
4. FROM python:3.14-slim
ENV PYTHONDONTWRITEBYTECODE=1
COPY app /app
RUN python -m compileall -q /app # obraz yig'ilganda kompilyatsiya
CMD ["python", "-m", "app"]
5. # Bu kod to'g'ri: import qilinayotgan modulning SyntaxError i shu faylni emas,
# import paytidagi kompilyatsiyani buzadi va ushlanadi. Lekin xatoni yashirmaslik uchun:
try:
import yangi_modul
except SyntaxError as xato:
log.error("yangi_modul buzilgan: %s", xato)
raiseVazifa 3: Konveyer ko'ruvchi
konveyer.py CLI vositasini yozing (argparse, 15-qism):
python konveyer.py fayl.py --bosqich tokens|ast|symtable|code|distokens— turlar bo'yicha statistika va birinchi N tokenast—ast.dump(indent=2)va tugun turlari sonisymtable— har funksiya uchun local/global/free/cell nomlar jadvalicode— barcha ichki kod obyektlari daraxti: nom, qator, bayt-kod hajmi, konstantalar soni
Vazifa 4: .pyc inspektori
pyc_info(yol) funksiyasini yozing:
- Sarlavhani o'qib, rejim (vaqt belgisi / tekshiriladigan xesh / tekshirilmaydigan xesh) va Python versiyasini (magic raqamdan) aniqlasin
- Manba fayl mavjud bo'lsa,
.pycyaroqliligini tekshirsin - Kod obyektlari daraxtidagi barcha funksiyalar ro'yxatini chiqarsin
compileallbilan loyihangizning__pycache__papkasiga qo'llang va eskirgan.pyclarni toping
Vazifa 5: Sintaksis kengaytmasi
ast.NodeTransformer (10-qism bilan bog'lang) yordamida "import hook" siz transformator yozing:
x |> f |> go'rnigaozgartir("x |> f", ...)kabi funksiya: manbadagi>>operatorinig(f(x))chaqiruviga aylantiradi (ast.BinOpvaast.RShift)- Qator raqamlarini
ast.copy_locationbilan saqlasin — traceback to'g'ri qatorni ko'rsatsin compilevaexecbilan bajarsin- Transformatsiyadan oldingi va keyingi manbani
ast.unparsebilan ko'rsating
Vazifa 6: Ishga tushish vaqti
Katta bog'liqliklarga ega loyiha (yoki 200 ta sun'iy modul yarating) uchun:
.pycsiz (-B, keshni tozalab) va.pycbilan import vaqtinitime.perf_counterbilan o'lchangpython -X importtimenatijasini tahlil qilib, eng sekin 10 modulni chiqaringPYTHONPYCACHEPREFIXbilan faqat o'qish papkasini simulyatsiya qiling- Natijani jadvalda ko'rsating va Docker uchun tavsiya yozing
Vazifa 7: O'ylash
Java kodni .class bayt-kodga kompilyatsiya qilib, JVM da JIT bilan bajaradi; Go va Rust to'g'ridan-to'g'ri mashina kodiga kompilyatsiya qiladi; JavaScript dvigatellari (V8) manbadan ish vaqtida bayt-kod va keyin JIT orqali mashina kodi yaratadi. CPython qaysi modelga yaqin, uning "kompilyatsiya" si Java'nikidan nimasi bilan farq qiladi va bu farq ishga tushish vaqti, tarqatish va xatolarni topishga qanday ta'sir qiladi?
Javob
Qisqa javob: CPython modeli Java va V8 o'rtasida: Java kabi alohida bayt-kod bosqichi va keshlangan fayl (.pyc ↔ .class) bor, lekin kompilyatsiya dasturchi tomonidan emas, import paytida avtomatik va deyarli hech qanday tekshiruvsiz bajariladi. Bayt-kod mashina kodiga emas, interpretatorda bajariladi (3.13+ tajribaviy JIT bundan mustasno). Natijada ishga tushish tez va tarqatish oddiy, lekin turlar va nomlar xatolari faqat ish vaqtida chiqadi.
1. Modellar
| Til | Kompilyatsiya | Bajarilish | Tur tekshiruvi |
|---|---|---|---|
| C, Go, Rust | Oldindan → mashina kodi | To'g'ridan-to'g'ri CPU | Kompilyatsiyada |
| Java, C# | Oldindan (javac) → bayt-kod |
JVM: interpretator + JIT | Kompilyatsiyada |
| JavaScript (V8) | Ish vaqtida → bayt-kod (Ignition) | Interpretator + JIT (Maglev, TurboFan) | Yo'q |
| CPython | Import paytida → bayt-kod (.pyc) |
Interpretator (3.11+ ixtisoslashuv, 3.13+ tajribaviy JIT) | Yo'q (faqat tashqi vositalar) |
2. Java bilan farq
javacalohida qadam: turlar, nomlar, imzolar tekshiriladi — xatolar ishga tushishdan oldin topiladi- CPython kompilyatori faqat sintaksis va ko'rinish sohalarini tekshiradi;
nomalum()va1 + "a"kompilyatsiyadan o'tadi - Java bayt-kodi tipli (
iadd,dadd), CPython bayt-kodi umumiy (BINARY_OP) — turni ish vaqtida aniqlaydi va 3.11+ da bunga moslashadi (ixtisoslashuv) .classfayllar — tarqatish birligi (JAR);.pyc— shunchaki kesh, manba bilan birga tarqatiladi
3. V8 bilan o'xshashlik
- Ikkalasi ham manbadan avtomatik bayt-kod yaratadi va turlar haqida ish vaqtida ma'lumot yig'adi
- V8 bu ma'lumot bilan agressiv JIT qiladi; CPython 3.11+ adaptiv interpretatori shu yo'lning birinchi qadami (12.8-dars)
4. Ta'siri
| Jihat | CPython oqibati |
|---|---|
| Ishga tushish | Kompilyatsiya tez, .pyc bilan yanada tez; lekin import qilinadigan modul kodi bajariladi — og'ir importlar ishga tushishni sekinlashtiradi |
| Tarqatish | Manba + (ixtiyoriy) .pyc; Python versiyasiga bog'liq; bitta binar fayl yo'q (PyInstaller, Nuitka — alohida vositalar) |
| Xatolarni topish | Faqat sintaksis oldindan; qolgani — testlar, mypy/pyright (13-qism), ruff (18-qism) |
| Tezlik | Interpretator narxi — hisoblash og'ir qismlar C kengaytmalar (NumPy) yoki boshqa tillarga (30-qism) |
| Moslashuvchanlik | exec, eval, compile, AST transformatsiyalari — ish vaqtida kod yaratish oson |
5. Xulosa
- CPython kompilyatsiya qiladi, lekin bayt-kodga va import paytida avtomatik
- Java'dan farqi: tur tekshiruvi yo'q, bayt-kod tipsiz,
.pyc— tarqatish birligi emas, kesh - V8 ga yaqin: ish vaqtida tur ma'lumotiga moslashish (ixtisoslashuv, JIT)
- Amalda: ishga tushish uchun
compileall, xatolar uchun statik tahlil va testlar, tezlik uchun C kengaytmalar
Nimani mustahkamlaydi: 2.1–2.7-bo'limlar.
Xulosa
Bu darsda Python kodining bajarilish konveyerini o'rgandik.
Eng muhim uch fikr:
CPython avval kompilyatsiya qiladi, keyin bajaradi. Manba tokenlarga, tokenlar PEG parser orqali AST ga aylanadi,
symtablehar nomning ko'rinish sohasini (local, global, free, cell) belgilaydi, kompilyator esa optimallashtirilgan bayt-kodli kod obyekti yaratadi. Butun modul bajarilishdan oldin kompilyatsiya qilinadi: sintaksis xatosi birinchi qatorni ham bajartirmaydi,NameErroresa faqat ish vaqtida chiqadi.Kod obyekti — o'zgarmas bajarish birligi.
co_code,co_consts,co_names,co_varnames,co_freevars,co_lines()— hammasi unda. Funksiya kod obyektini global muhit, sukut qiymatlar va closure bilan bog'laydi; bitta kod obyektidan ko'p funksiya yaratilishi mumkin. Dinamik kodni bir martacompileqilib, kod obyektini qayta ishlatish —evalni o'nlab barobar tezlashtiradi..pyc— kompilyatsiya keshi, tezroq kod emas. Import qilingan modul__pycache__/modul.cpython-314.pycga yoziladi: 16 baytli sarlavha (magic, bayroqlar,mtime+hajm yoki xesh) vamarshalqilingan kod obyekti. Faqat o'qish fayl tizimlaridacompileallni obraz yig'ish bosqichida bajaring;-O/-OOfaqatassert,__debug__va docstringlarni olib tashlaydi.
Keyingi darsda bayt-kodning o'zini o'qishni o'rganamiz: dis moduli, instruksiyalar va ularning argumentlari, stek effekti, sikllar, shartlar va funksiya chaqiruvlari bayt-kodda qanday ko'rinishi.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!