1. Ce înseamnă „independent de platformă”
Un program independent de platformă rulează pe mai multe sisteme de operare și arhitecturi hardware fără modificări ale codului sursă. Aceasta este definiția din curriculum, iar întrebarea interesantă nu este ce înseamnă, ci cum se obține.
Ați studiat deja mecanismul Java: compilatorul javac transformă sursa în bytecode .class, iar mașina virtuală Java îl execută pe orice sistem pentru care există o implementare de JVM. Python folosește aceeași idee, cu o singură diferență de formă:
| Etapă | Java | Python |
|---|---|---|
| Compilare | pas explicit, javac |
automat, la prima rulare sau la import |
| Rezultat intermediar | .class |
.pyc în __pycache__ |
| Execuție | JVM | PVM — mașina virtuală Python |
| Verificarea tipurilor | la compilare | la rulare |
Portabilitatea nu vine dintr-o singură componentă, ci din patru straturi suprapuse:
- Codul sursă — identic pe toate platformele.
- Interpretorul — traduce operațiile în apeluri specifice sistemului gazdă.
- Biblioteca standard — oferă un API unic peste apeluri de sistem care diferă (
pathlib,os,socket). - Sistemul de operare — aici se află diferențele reale.
2. Cum execută Python un program
La lansarea unui script se întâmplă două lucruri, în ordine:
app.py → compilare automată → bytecode (__pycache__/app.cpython-313.pyc)
│
▼
PVM (mașina virtuală Python)
│
▼
apeluri de sistem
Bytecode-ul poate fi inspectat cu modulul dis din biblioteca standard:
import dis
def suma(a, b):
return a + b
dis.dis(suma)
# 2 RESUME 0
# 3 LOAD_FAST a
# LOAD_FAST b
# BINARY_OP 0 (+)
# RETURN_VALUE
Din acest mecanism decurg patru consecințe practice pe care le veți întâlni imediat:
- Erorile de sintaxă apar înainte de rulare. Un fișier cu o paranteză neînchisă nu se execută deloc, nici măcar prima linie.
- Erorile de tip apar la rulare. Spre deosebire de Java, nimic nu verifică tipurile înainte de execuție. Adnotările de tip (tema 4) plus
mypyrecuperează parțial această verificare. - Bytecode-ul nu este portabil între versiuni. Un
.pycgenerat de Python 3.12 nu este citit de 3.13. Sursa, în schimb, da. Folderul__pycache__este doar un cache: se poate șterge oricând. - Viteza are un cost. Interpretarea este mai lentă decât codul compilat nativ. Părțile critice se scriu în C sau se deleagă unor biblioteci native (NumPy, OpenCV).
3. Implementări ale limbajului
„Python” denumește limbajul, nu programul care îl execută. Există mai multe implementări, iar alegerea contează în această disciplină:
| Implementare | Scrisă în | Puncte tari | Când o alegeți |
|---|---|---|---|
| CPython | C | implementarea de referință, toate bibliotecile | implicit, în aproape toate cazurile |
| PyPy | RPython | compilare JIT, de 3–10 ori mai rapid la calcul pur | cod intensiv în CPU, fără extensii C |
| MicroPython | C | rulează pe microcontrolere, cu câțiva KB de RAM | ESP32, STM32, plăci embedded |
| Jython | Java | rulează pe JVM, interoperabil cu clase Java | integrare în sisteme Java existente |
| IronPython | C# | rulează pe .NET | integrare în ecosistem .NET |
Codul care trebuie să se adapteze mediului trebuie mai întâi să afle unde rulează:
import sys, platform
print(sys.implementation.name) # cpython
print(platform.python_version()) # 3.13.2
print(platform.system()) # Windows / Linux / Darwin
print(platform.machine()) # AMD64 / x86_64 / aarch64
4. Mediul de lucru
Verificarea instalării
python --version # Windows
python3 --version # Linux / macOS
py -0 # Windows: toate versiunile instalate
py -3.13 script.py # rulare cu o versiune anume
python; pe Linux și macOS este python3. Acolo, python poate să nu existe deloc sau să trimită la versiunea 2. Este prima diferență de platformă pe care o întâlniți.Mediul virtual
Fără izolare, toate proiectele de pe calculator împart aceleași pachete și aceleași versiuni. Primul conflict — un proiect cere flask 2.x, altul flask 3.x — blochează ambele proiecte. Mediul virtual creează o copie izolată a interpretorului și a pachetelor, pentru fiecare proiect:
python -m venv .venv # creează mediul în folderul .venv
.venv\Scripts\activate # activare pe Windows
source .venv/bin/activate # activare pe Linux / macOS
pip install flask pyserial # se instalează DOAR în acest mediu
pip freeze > requirements.txt # fixează versiunile exacte
deactivate # ieșire din mediu
Perechea venv + requirements.txt este prima formă concretă de independență de platformă din acest curs: proiectul își poartă cu el rețeta de instalare, iar pe orice alt calculator mediul se reface identic printr-o singură comandă.
| Comandă | Efect |
|---|---|
pip install pachet |
instalează ultima versiune |
pip install pachet==2.1.0 |
instalează o versiune fixă |
pip list |
listează ce este instalat în mediul activ |
pip show pachet |
versiune, dependențe, locație |
pip freeze > requirements.txt |
salvează starea mediului |
pip install -r requirements.txt |
reface mediul din fișier |
pip install fără mediul activat, apoi programul raportează ModuleNotFoundError. Comanda pip -V arată calea exactă a mediului în care lucrați.5. Rularea programului
python app.py # rulare directă a fișierului
python -m pachet # rulare a unui pachet (folosește __main__.py)
python -m http.server 8000 # rulare a unui modul din biblioteca standard
python -i app.py # rulează, apoi lasă interpretorul deschis
A treia formă merită reținută: python -m http.server 8000 pornește un server web în folderul curent, fără nicio linie de cod și fără nicio instalare. Rezolvă integral prima cerință a lucrării practice 1 — servirea unei pagini index.html pe localhost.
Punctul de intrare
def main():
print("Aplicația pornește")
if __name__ == "__main__":
main()
Variabila __name__ are valoarea "__main__" doar când fișierul este rulat direct, nu și când este importat din alt modul. Această construcție separă codul executabil de cel reutilizabil. Pare o formalitate acum; în tema 6 devine obligatorie, pentru că fără ea multiprocessing pe Windows intră în recursie infinită.
6. Ce rămâne dependent de platformă
Aceasta este partea cea mai importantă a temei. Interpretorul rezolvă portabilitatea limbajului; restul rămâne în sarcina voastră.
Căile de fișiere
# GREȘIT — separator scris de mână
cale = "date\\masuratori.csv" # merge doar pe Windows
# CORECT — pathlib construiește calea potrivită sistemului
from pathlib import Path
cale = Path("date") / "masuratori.csv"
cale.parent.mkdir(parents=True, exist_ok=True)
BAZA = Path(__file__).parent / "date" # independent de folderul de lansare
Ultima linie merită atenție: o cale relativă precum "date/fisier.csv" se interpretează față de folderul din care porniți programul, nu față de locul unde se află fișierul sursă. Construind calea din __file__, programul funcționează indiferent de unde este lansat.
Codificarea și sfârșitul de linie
# Windows scrie CRLF, Linux și macOS scriu LF
# codificarea implicită diferă: cp1252 pe Windows, utf-8 pe Linux
with open("date.csv", "w", encoding="utf-8", newline="") as f:
f.write("nume,valoare\n")
encoding="utf-8" este cauza numărul unu a diacriticelor stricate atunci când fișierul trece de pe un sistem pe altul. Parametrul newline="" este obligatoriu la lucrul cu modulul csv, altfel pe Windows apar rânduri goale între înregistrări.| Aspect | Diferența | Soluția portabilă |
|---|---|---|
| Căi | \ vs /, litere de unități |
pathlib.Path |
| Codificare | cp1252 / utf-8 implicit | encoding="utf-8" explicit |
| Sfârșit de linie | CRLF vs LF | mod text, newline="" |
| Variabile de mediu | %VAR% vs $VAR |
os.environ |
| Porturi seriale | COM3 vs /dev/ttyUSB0 |
serial.tools.list_ports |
| Procese noi | spawn vs fork | multiprocessing.set_start_method |
| Folder temporar | %TEMP% vs /tmp |
tempfile |
Când nu există abstracție potrivită, ramificați explicit — dar abia atunci:
import sys
if sys.platform.startswith("win"):
port_implicit = "COM3"
elif sys.platform.startswith("linux"):
port_implicit = "/dev/ttyUSB0"
else: # darwin
port_implicit = "/dev/tty.usbserial"
7. Distribuirea aplicației
| Formă | Cum se obține | Rulează pe |
|---|---|---|
Sursă + requirements.txt |
arhivă sau depozit Git | orice sistem cu Python instalat |
Pachet .whl |
python -m build |
orice sistem, prin pip install |
| Executabil | pyinstaller --onefile app.py |
doar platforma pe care a fost construit |
PyInstaller împachetează interpretorul și bibliotecile native ale sistemului pe care rulează. Un .exe construit pe Windows nu rulează pe Linux. Pentru fiecare platformă este nevoie de o construcție separată, de obicei printr-un pipeline de integrare continuă. Este limita cea mai concretă a principiului „write once, run everywhere”.8. Greșeli tipice
| Simptom | Cauză și rezolvare |
|---|---|
python nu este recunoscut |
Interpretorul nu este în PATH sau se numește python3 |
ModuleNotFoundError după pip install |
Ați instalat în alt mediu decât cel activ. Verificați cu pip -V |
| Programul merge la voi, nu și la coleg | Dependențe neînghețate. Livrați requirements.txt |
| Diacritice stricate în fișier | Lipsește encoding="utf-8" la open() |
| Calea nu se găsește pe Linux | Separator \ scris manual. Folosiți pathlib |
| Fișierul nu se găsește la rularea din alt folder | Cale relativă. Construiți-o din Path(__file__).parent |
.exe nu pornește pe alt calculator |
Construcție pe altă platformă sau bibliotecă lipsă |
9. Întrebări de autoverificare
- Prin ce diferă mecanismul de portabilitate al Python de cel al Java?
- La ce folosește folderul
__pycache__și ce se întâmplă dacă îl ștergeți? - Când ați alege PyPy în loc de CPython? Dar MicroPython?
- De ce un mediu virtual per proiect și nu o singură instalare globală?
- Numiți trei lucruri care rămân dependente de platformă și abstracția care le rezolvă.
- De ce o cale relativă poate funcționa la voi și eșua la coleg, chiar pe același sistem?
- De ce un executabil creat cu PyInstaller pe Windows nu rulează pe Linux?
