A helyzet: az 2.3-ben felépített helyi Git-repót egy másik gépre
visszük át, és azon egy tiszta könyvtárban futtatjuk a Northstar
kezdőlabor ellenőrzőjét. A bemenet a klónozott lab projekt
és a szállított CSV-k; egy megfigyelési egység egy teljes futtatási
munkamenet az adott gépen. A cél kettős: (1) a három szerződött
adatméret ellenőrzése a másik gépen is ugyanazt az eredményt adja, és
(2) ha a futás eltér, a hibát az operációs rendszer, a fájljog vagy az
interpreter szintjére tudjuk besorolni, ne pedig automatikusan
algoritmushibának gondoljuk.
Előzetes becslés: a quickcheck.py sikeres futása
customers=300, orders=2400,
order_items=4796 kontrollértékeket és nulla kilépési kódot
ad. Ez a három szám az adatszerződésből származó invariant; ha bármelyik
eltér, az hibát jelez, de a hiba típusát még nem mondja meg. Ebben az
alfejezetben pontosan ezt a szétválasztást gyakoroljuk.
Egy „másik gép, azonos projekt” forgatókönyvben három különböző réteget érdemes megkülönböztetni:
Az operációs rendszer és fájlrendszer. A Windows
alapértelmezett fájlrendszer-szemantikája különbözik a Linuxétól és a
macOS-étől. A Windows útvonala C:\Users\anna\projekt, a
POSIX rendszereké /home/anna/projekt; a Windows a backslash
(\) elválasztót várja a héjban, a Python
pathlib azonban mindkettőn a / jelet is
elfogadja. A Linux fájlnevei kis- és nagybetű-érzékenyek
(case-sensitive), a Windows és az alapbeállítású macOS fájlrendszer nem.
Emiatt a Orders.CSV elnevezés Linuxon más fájl, mint az
orders.csv, Windows-on viszont ugyanarra mutathat. A sorvég
(line ending) is platformfüggő: Windows hagyományosan CRLF-et, Linux és
macOS LF-et használ. A Git text=auto beállítás nélkül ezt a
különbséget be tudja vinni a diffbe, ami zajt kelt a
review-ban.
A fájljogosultságok és a végrehajtási házirend.
POSIX rendszeren egy script közvetlen futtatásához executable bit
(futtathatósági bit) kell: chmod +x quickcheck.py, majd
./quickcheck.py. Windows-on ilyen bit nincs; ott a fájl
kiterjesztése és a társítás számít, a PowerShell pedig a scriptekre
külön végrehajtási házirendet (execution policy) alkalmaz. A
git clone a fájl jogosultsági bitjét a repóból hozza, ha az
ott commitolva volt; ha a scriptet Windowsról írták, a bit hiányozhat
Linuxon.
Az interpreter és a függőségek. A
python parancs nem ugyanaz minden gépen. Windows-on a
Microsoft Store-hoz irányíthat, ha nincs telepített interpreter; a
py -3.12 launcher viszont konkrét verziót kér. Linuxon
gyakran a python3 a helyes név, a python pedig
hiányozhat. A virtuális környezet (venv) a géphez és a fájlúthoz kötött:
a benne levő bin/python (POSIX) vagy
Scripts/python.exe (Windows) nem hordozható a gépek között.
A uv sync vagy a requirements.txt a
függőségeket oldja fel, de az alapinterpretert a felhasználónak kell
biztosítania. Ezek a különbségek mind környezethibák,
nem pedig a kód logikájának hibái.
A WSL (Windows Subsystem for Linux) egy további réteg: a
Windows-gazdarendszeren belül futó Linux-környezet, saját
fájlrendszerrel, saját processztérrel és saját Python-telepítéssel. A
WSL-ből a Windows meghajtó a /mnt/c alatt látszik, a
Windowsból a WSL-fájlrendszer a
\\wsl.localhost\<disztribúció> útvonalon. A kettő
nem ugyanaz a fájl- és processzkörnyezet: a Windowsban
telepített Python nem látja a WSL-beli virtuális környezet csomagjait,
és fordítva. Egy Docker-konténer szintén külön fájl- és
processzkörnyezet; a konténer munkakönyvtára alapértelmezésben nem a
gazdagép projektmappája.
A parancssor szintjén a POSIX-héj (Bash, zsh) és a PowerShell parancsai eltérnek. A leggyakoribb megfeleltetések:
| Feladat | POSIX (Linux, macOS, WSL) | PowerShell (Windows) |
|---|---|---|
| Könyvtár listázása | ls -la |
Get-ChildItem -Force |
| Munkakönyvtár | pwd |
Get-Location |
| Szövegfájl sorainak számolása | wc -l fajl.csv |
(Get-Content fajl.csv).Count |
| Fájl hash | sha256sum fajl |
Get-FileHash fajl -Algorithm SHA256 |
| Környezeti változó | echo "$HOME" |
echo $env:USERPROFILE |
| Fájl másolása | cp a b |
Copy-Item a b |
A táblázat nem teljes szótár, hanem annak illusztrációja, hogy ugyanaz a szándék más szintaxist igényel. A platformfüggő parancsok aktuális viselkedését a saját gép dokumentációja és a sources.md kulcsai alapján ellenőrizzük; ezt az alfejezetet nem konkrét webes futtatásból írjuk.
A példa bemenete a már létező helyi repó. A cél: a másik gépen a
git clone után csak a repóban levő
fájlokkal futtatni a kontrollt, semmilyen korábbi munkakönyvtárból
örökölt állapottal.
Linuxon vagy macOS-en (Bash):
# A repót a lokális elérési útvonalról klónozzuk; távoli repónál URL jönne.
git clone /mnt/shared/northstar-lab northstar-bash
cd northstar-bash
# Interpreter-ellenőrzés: a projekt kiinduló célja Python 3.12.
python3 --version
# A függőségmentes kontroll futtatása tiszta klónból.
python3 quickcheck.pyWindows PowerShellben:
git clone C:\src\northstar-lab northstar-win
cd northstar-win
# A launcher konkrét verziót keres, ha több Python is telepítve van.
py -3.12 --version
py -3.12 quickcheck.pyA quickcheck.py a mellékelt CSV-ket ellenőrzi a manifest
és az adatszerződés alapján. Szemléltető, elméletileg várt kimenet (a
tanuló saját futtatása a mérvadó; ez a kimenet nem a könyvírás során
mért futás):
customers rows=300 OK
orders rows=2400 OK
order_items rows=4796 OK
all checks passed
exit code: 0
A WSL-beli változathoz ugyanaz a Bash-szekvencia tartozik, de a klón
célja a WSL saját fájlrendszerén belül legyen, például
~/northstar-wsl, nem pedig /mnt/c/..., mert a
/mnt/c alatti munka lassabb és eltérő
jogosultság-szemantikát adhat.
A kontroll akkor sikeres, ha a három sorban a szerződött méretek szerepelnek, és a kilépési kód 0. Ez a három szám nem mérés, hanem az adatszerződés invariánsa: a generátor alap seedjével készült fájlok rögzített sorméretei. Ha a fájlok a klónozás során változtak volna, a manifest hash-ellenőrzése ezt a sorszám-ellenőrzés előtt vagy mellett kimutatná.
Érdemes a quickcheck.py futását egy kézi kontrollal is
plauzibilissé tenni, amikor a sorok számát a platform saját eszközével
is megnézzük:
# Linux/macOS/WSL: a CSV első sora fejléc, tehát adatsor = sorok - 1.
wc -l data/customers.csv# PowerShellben ugyanez; a Count a fejlécsorral együtt számol.
(Get-Content data\customers.csv).CountHa a két szám 300 (adatsor) plusz 1 fejlécsor, akkor a szemcsézettség
egyezik. A wc -l csak akkor megbízható, ha a CSV-ben nincs
beágyazott sortörés; a Northstar szintetikus adatában ez a szerződés
része, más adatnál a CSV-értelmező a hiteles.
A példa lényege nem a három szám memorizálása, hanem az, hogy ugyanaz a repó ugyanazt a kontrollt adja három különböző környezetben. Ha az egyik gépen az eredmény eltér, a hibakeresés sorrendje:
python --version más verziót ad-e, mint a projekt célja?
Van-e aktív, másik projektből származó venv?python3 script.py módon?Átviteli próba. A másik gépen futó azonos kód nem garantálja az azonos környezetet. Ellenőrizni kell az interpreter pontos verzióját, a függőségi rögzítést, a fájlkódolást, a sorvégeket, az architektúrát és a könyvtárjogokat. A futási jegyzőkönyvben a környezeti eltérés és az adateltérés külön hibakategória legyen.
A python3 quickcheck.py használata kikerüli a
végrehajtási bit szükségességét, de nem garantálja,
hogy a helyes interpreter érhető el, hogy a fájl olvasható, vagy hogy
minden platformfüggőség teljesül. Ezért a »mindig működik« állítás
helyett a konkrét előfeltételeket kell megadni.
Értelmezés. Egy társ Windows PowerShellben a
python quickcheck.py parancs után ezt az üzenetet kapja:
Python was not found; run without arguments to install from the Microsoft Store.
Melyik réteg hibája ez? Miért nem jelenti azt, hogy a
quickcheck.py algoritmusa rossz? Mit javasolj neki első
lépésben?
Implementálás. Készíts egy
launch_checklist.md nevű fájlt a repó dokumentációs
mappájába. A lista három rovatot tartalmazzon: Linux/macOS, Windows
PowerShell és WSL. Minden rovathoz írd be sorrendben: (a) a repó
klónozása tiszta könyvtárba, (b) a Python-verzió ellenőrzése, (c) a
projekt gyökerébe lépés, (d) a quickcheck.py futtatása, (e)
a három elvárt kontrollérték rögzítése. A fájl legyen platformtáblával
ellátott, hogy a társ a parancsok megfeleltetését is lássa.
Hibadiagnózis. Egy Linuxos gépen a társ ezt
futtatja: ./quickcheck.py, és ezt kapja:
Permission denied. Ugyanott a
python3 quickcheck.py sikeresen lefut. Mi a különbség a két
parancs között? Melyik a helyes hosszú távú megoldás, ha a repó a
scriptet parancsként szeretné futtatni, és mit nem
szabad megtennie a diagnózis során?
Megváltozott feltétel. A projektet egy macOS
gépre viszed, ahol a python3 --version 3.11-et ír, a
pyproject.toml pedig
requires-python = ">=3.12"-t rögzít. A
quickcheck.py mégis hiba nélkül fut, mert standard
library-only. A starter_experiment.py azonban
csomaghiánnyal bukik, amikor uv sync nélkül próbálod
futtatni. Írd le, milyen kimenetből látod, hogy ez
környezethiba, nem a kísérleti kód hibája, és milyen
parancsokkal jutsz el a kontrollfutásig anélkül, hogy a Python 3.11-et
kézzel felülírnád a rendszerben.
Megoldás. Ez interpreter-réteg-hiba: a
python parancs a Microsoft Store által nyújtott álparancsra
mutat, nem egy telepített CPythonra. A quickcheck.py
hibátlan lehet; a bemenetet és a kódot meg sem kapta. Első lépés a
py -3.12 --version vagy a python --version
futtatása, illetve a telepített Python keresése a py -0
launcherrel. Ha nincs 3.12, a környezetet a projekt elvárásának
megfelelően kell telepíteni; a kódhoz nem nyúlunk.
Megoldás. A lényeg az ellenőrzőlista platformrovata. Egy lehetséges minimális változat:
# Indítási ellenőrzőlista
| Lépés | Linux/macOS | Windows PowerShell | WSL |
|---|---|---|---|
| Klón | `git clone <repó> ~/northstar` | `git clone <repó> C:\work\northstar` | `git clone <repó> ~/northstar-wsl` |
| Lépés a gyökérbe | `cd ~/northstar` | `cd C:\work\northstar` | `cd ~/northstar-wsl` |
| Python-verzió | `python3 --version` | `py -3.12 --version` | `python3 --version` |
| Ellenőrző | `python3 quickcheck.py` | `py -3.12 quickcheck.py` | `python3 quickcheck.py` |
| Elvárt értékek | 300 / 2400 / 4796; exit 0 | ugyanaz | ugyanaz |
A cél: ugyanaz a három kontrollérték mindhárom környezetben.Az elvárt értékek sor: customers=300,
orders=2400, order_items=4796, és a kilépési
kód 0. Ha a klón forrása nem a szállított repó, a hash-ellenőrzés is
kötelező.
Megoldás. A ./quickcheck.py a
fájlban levő shebang-et és a futtathatósági bitet használja; a
python3 quickcheck.py explicit módon az interpretert hívja.
A Permission denied azt jelenti, hogy a fájl nem futtatható
közvetlenül, mert a bit hiányzik. A helyes hosszú távú megoldás, ha a
scriptet parancsként akarjuk futtatni:
chmod +x quickcheck.py, és a fájl első sora
#!/usr/bin/env python3 legyen, majd ezt commitolni.
Nem szabad a diagnózis során a rendszer
Python-telepítését globálisan átírni, vagy a chmod-ot
kihagyva Windowsról áthozott bitre támaszkodni. A
python3 quickcheck.py a futtathatósági bittől függetlenül
indítható, ha a megfelelő Python-interpreter elérhető, a fájl olvasható,
és a szükséges függőségek telepítve vannak, ezért a kontroll
szempontjából biztonságosabb.
Megoldás. A környezethibára utaló jelek: a
starter_experiment.py által importált csomag nevére
vonatkozó ModuleNotFoundError, vagy a
pyproject.toml Python-korlátjára hivatkozó
uv-üzenet. Ez nem a kísérleti statisztika hibája; a script
importálás előtt áll meg. A megoldás: telepíteni a projekt által elvárt
3.12-t (például uv python install 3.12), a projektben
uv sync-kel feloldani a függőségeket, majd
uv run python starter_experiment.py módon futtatni, ami a
projekt környezetéhez köti az interpretert. A rendszer 3.11-ét nem kell
felülírni; az uv a projektvenv-ben külön 3.12-t kezel. A
quickcheck.py azért futott, mert standard library-only, így
a függőségek hiánya nem érintette. A kettő különbsége pontosan mutatja
az interpreter- és függőségi réteg szerepét.
Gyakori tévedés: azt hinni, hogy a Windows, a WSL és
a Docker ugyanazt a fájl- és processzkörnyezetet jelenti. Ellenpélda: a
felhasználó a WSL-ben létrehoz egy virtuális környezetet a
/home/anna/venv alatt, majd a Windows PowerShellben
aktiválni próbálja a
\\wsl.localhost\...\venv\Scripts\activate fájlt. A Windows
Python nem a WSL-beli bin/python-t használja, a csomagok
nem látszanak, és a ModuleNotFoundError elsőre
algoritmushibának tűnik. A javítás a rétegek szétválasztása: a
PowerShellben a Windows saját Pythonját és venv-jét kell használni, a
WSL-ben pedig a WSL-beli környezetet. A Docker-konténer szintén külön: a
konténerben futó script nem a gazdagép munkakönyvtárát látja
automatikusan, csak a becsatolt kötetet.
Visszautalás. Az 1.4-ben a három hibacsalád a programozási, adatértelmezési és statisztikai hiba volt. Ez az alfejezet az első családon belül azonosít további rétegeket: az operációs rendszer, a fájljog és az interpreter hibái mind a kód futtatása előtt jelentkeznek, ezért nem szabad a statisztikai következtetés hibájának tekinteni őket. Az 2.3-ben a Git-réteg tanította, hogy a repó a projektet viszi, nem a gép állapotát; itt ennek következménye, hogy a klón után a környezetet mindig újra kell ellenőrizni.
Önellenőrzés. (1) Ha a quickcheck.py
két gépen ugyanazt a három számot adja, akkor biztos, hogy a modell is
ugyanazt fogja adni? Nem; a kontroll csak a bemenő adatméretet és a
környezet egy részét ellenőrzi. (2) Melyik parancs mutatja meg először,
hogy a python a Microsoft Store csapdájára mutat? A
python --version hibaüzenete vagy a launcher hiánya. (3)
Miért hibás a chmod-dal kapcsolatosan a „Windowsról hozott
jogosultság” feltételezése? Mert a Windows-fájlrendszeren nincs POSIX
futtathatósági bit; a bit a Git által tárolt metainformációból
származik, ha a repóban rögzítve volt.
Egy projekt másik gépen akkor folytatható, ha az operációs rendszer,
a fájljog és az interpreter különbségeit nem keverjük a kód hibájával. A
Linux, macOS, Windows és WSL eltérő fájlrendszer-szemantikát, sorvég- és
jogosultságkezelést hoz; a PowerShell és a POSIX-héj parancsai más
szintaxisúak ugyanarra a szándékra. A tiszta klónból futtatott
quickcheck.py a szerződött 300/2400/4796 kontrollértékkel
ellenőrzi, hogy a projekt bemenete azonos. A hibadiagnózis sorrendje:
interpreter, fájl-útvonal, fájljog, és csak ezek után algoritmus. A
következő alfejezetben ezt a réteget tovább szűkítjük: a Python-verziót
és a csomagfüggőségeket izolált környezetbe zárjuk.