Wiki 5: Files, Exceptions na Virtual Environments
Mwezi 2 | Lengo kuu: Mwanafunzi aweze kusoma na kuandika files (txt, CSV, JSON), kushughulikia makosa kwa
try/except, na kutengeneza virtual environment yenyerequirements.txt.
Maandalizi ya Mwalimu (soma kabla ya wiki kuanza)
- Soma:
- Python Tutorial — "Reading and Writing Files": https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files
- Python Tutorial — "Errors and Exceptions": https://docs.python.org/3/tutorial/errors.html
venvdocs: https://docs.python.org/3/library/venv.html
- Fanya mazoezi mwenyewe kwanza: andika code zote za sehemu "Andika code hii live" kwenye kompyuta yako ya kwanza KABLA ya kipindi. Usiandike code kwa mara ya kwanza mbele ya mwanafunzi.
- Andaa folder:
C:\Users\<jina>\Documents\python_kozi\wiki05\na ufungue folder hilo kwenye VS Code (File → Open Folder). Hii ni muhimu kwa sababu files zinazoundwa na Python zitaonekana upande wa kushoto (Explorer). - Hakikisha:
python --versioninaonyesha 3.12 au zaidi kwenye PowerShell. Hakikisha una internet kwa Kipindi 3 (pip itapakua packages). - Kidokezo: Kwenye Windows, files zinaweza kuwa na encoding tofauti. Tutatumia
encoding="utf-8"KILA mara tunapofungua file la maandishi — hii inazuia makosa ya herufi kama "é" au emoji.
Malengo ya Wiki (mwisho wa wiki mwanafunzi ataweza...)
- Kufungua file kwa
open()nawith, na kueleza modes"r","w","a". - Kusoma file nzima, mstari kwa mstari, na kuandika/kuongeza maandishi.
- Kutumia
pathlib.Pathkujenga njia (paths), kuangalia kama file lipo, na kusoma/kuandika kwa haraka. - Kusoma na kuandika CSV kwa
csv.reader,csv.writer,csv.DictReader,csv.DictWriter. - Kuhifadhi na kusoma data kwa JSON (
json.dump,json.load,json.dumps,json.loads). - Kutumia
try / except / else / finallyna kuchagua exception sahihi. - Kutumia
raisena kutengeneza custom exceptions. - Kutengeneza na ku-activate virtual environment kwenye PowerShell, kusakinisha package kwa
pip, na kutengenezarequirements.txt.
Kipindi 1 — Files: open, with, txt na pathlib
Mtiririko wa kipindi
- Marudio ya kazi ya nyumbani ya Wiki 4 (modules) + salamu
- Kwa nini files?
open(), modes,close() withstatement — live coding: kuandika na kusoma file- Kusoma mstari kwa mstari,
strip(), mode"a" - Mapumziko mafupi
pathlib.Path— paths,exists(),read_text(),write_text()- Zoezi darasani
- Q&A + kazi ya nyumbani
Elezo kwa mwalimu (soma kwanza wewe)
Mpaka sasa, data zote za programu zetu zinapotea programu inapoisha (variables zinaishi kwenye RAM). File ni njia ya kuhifadhi data kwenye disk ili ibaki hata kompyuta ikizimwa.
open(jina, mode, encoding) inarudisha "file object". Modes muhimu:
"r"— read (soma). Ni default. File lisipokuwepo →FileNotFoundError."w"— write (andika). Inafuta maudhui yaliyokuwepo! Kama file halipo, linaundwa."a"— append (ongeza mwishoni). Haifuti kilichokuwepo."x"— create; inashindwa kama file tayari lipo (FileExistsError).
Baada ya kufungua lazima ufunge (f.close()), vinginevyo data inaweza isiandikwe kikamilifu. Ndio maana tunatumia with — "context manager" — inafunga file yenyewe hata kama kosa limetokea ndani.
Njia za kusoma:
f.read()→ string moja yenye kila kitu.f.readlines()→ list ya mistari (kila mmoja una\nmwishoni).for line in f:→ mstari mmoja mmoja (bora kwa files kubwa).
f.write(text) haiongezi \n yenyewe — lazima uiweke wewe. (Tofauti na print.)
Relative path kama "data.txt" inatafutwa kwenye current working directory (folder ambalo terminal iko). Kwenye VS Code, ukibofya "Run" ▶, terminal inaweza kuwa kwenye folder tofauti na la script! Ndio maana pathlib na Path(__file__).parent ni muhimu: inatupa folder ambalo script yenyewe iko.
pathlib.Path ni njia ya kisasa ya kushughulikia paths:
Path("data") / "majina.txt"— operator/inaunganisha sehemu za path (inafanya kazi Windows na Linux).p.exists(),p.is_file(),p.name,p.suffix,p.stem,p.parentp.read_text(encoding="utf-8"),p.write_text(text, encoding="utf-8")p.mkdir(parents=True, exist_ok=True)— tengeneza folderPath.cwd()— folder la sasa;p.glob("*.txt")— tafuta files
Sema hivi kwa mwanafunzi
- "Fikiria file kama daftari.
openni kufungua daftari. Mode"r"ni kusoma tu. Mode"w"ni kuchana kurasa zote na kuanza upya — hatari! Mode"a"ni kuendelea kuandika ukurasa unaofuata." - "
withni kama mlango wa kujifunga wenyewe (automatic door). Ukitoka chumbani, mlango unajifunga hata kama ulikuwa unakimbia kwa sababu ya moto (kosa)." - "RAM ni ubao wa darasani — ukifutwa, umepotea. Disk ni daftari — unalibeba nyumbani."
- "
Pathni kama anwani ya nyumba: mkoa / wilaya / mtaa / nyumba. Tunaunganisha sehemu kwa/."
Andika code hii live (share screen)
Hatua 1: Tengeneza file files_intro.py.
# files_intro.py # Kuandika file kwa njia ya zamani (bila with) f = open("salamu.txt", "w", encoding="utf-8") f.write("Habari za asubuhi!\n") f.write("Karibu kwenye kozi ya Python.\n") f.close() print("Nimeandika file.")
Run kwenye terminal: python files_intro.py. Onyesha salamu.txt imetokea kwenye Explorer ya VS Code. Ifungue.
Hatua 2: Badilisha kutumia with, na soma file.
with open("salamu.txt", "w", encoding="utf-8") as f: f.write("Habari za asubuhi!\n") f.write("Karibu kwenye kozi ya Python.\n") with open("salamu.txt", "r", encoding="utf-8") as f: maudhui = f.read() print(maudhui) print(type(maudhui))
Output inayotarajiwa:
Habari za asubuhi! Karibu kwenye kozi ya Python. <class 'str'>
Uliza: "Kwa nini kuna mstari mtupu baada ya maandishi?" (Jibu: \n ya mwisho kwenye file + print inaongeza \n yake.)
Hatua 3: Mode "a" na kusoma mstari kwa mstari.
with open("majina.txt", "w", encoding="utf-8") as f: f.write("Asha\n") f.write("Baraka\n") with open("majina.txt", "a", encoding="utf-8") as f: f.write("Neema\n") with open("majina.txt", encoding="utf-8") as f: for namba, mstari in enumerate(f, start=1): print(namba, mstari.strip())
Output:
1 Asha 2 Baraka 3 Neema
Onyesha nini kinatokea bila .strip() (mistari mitupu katikati) — print(repr(mstari)) inaonyesha 'Asha\n'.
Hatua 4: Kuandika list kwa mara moja.
matunda = ["embe", "nanasi", "papai"] with open("matunda.txt", "w", encoding="utf-8") as f: for tunda in matunda: f.write(tunda + "\n") # au: f.write("\n".join(matunda) + "\n")
Hatua 5: pathlib.
from pathlib import Path folder_la_script = Path(__file__).parent print("Script iko:", folder_la_script) print("Terminal iko:", Path.cwd()) data = folder_la_script / "data" data.mkdir(exist_ok=True) faili = data / "kumbukumbu.txt" faili.write_text("Leo tumejifunza files.\n", encoding="utf-8") print(faili.exists()) # True print(faili.name) # kumbukumbu.txt print(faili.stem) # kumbukumbu print(faili.suffix) # .txt print(faili.read_text(encoding="utf-8")) for p in folder_la_script.glob("*.txt"): print("Nimeona:", p.name)
Eleza: write_text inafungua, inaandika, inafunga — kwa mstari mmoja. Ni rahisi kwa files ndogo.
Hatua 6: Onyesha kosa kwa makusudi:
with open("halipo.txt", encoding="utf-8") as f: print(f.read())
Output: FileNotFoundError: [Errno 2] No such file or directory: 'halipo.txt' — sema: "Kipindi 2 tutajifunza kushughulikia makosa kama haya. Kwa sasa tunaweza kuangalia kwanza kwa Path.exists()."
Maswali ya kumuuliza mwanafunzi
- Mode
"w"inafanya nini kama file tayari lina maandishi? — Inafuta kila kitu na kuanza upya. - Kwa nini tunapendelea
with? — Inafunga file yenyewe, hata kosa likitokea. f.write("Asha")mara mbili itatoa nini kwenye file? —AshaAsha(hakuna\nautomatically).f.read()inarudisha aina gani ya data? —str.- Tofauti ya
Path.cwd()naPath(__file__).parent? — cwd ni folder la terminal;__file__parent ni folder la script. - Unaongezaje jina jipya bila kufuta majina ya zamani? — Mode
"a".
Makosa ya kawaida
| Kosa | Ujumbe wa error | Suluhisho |
|---|---|---|
| File halipo au liko folder jingine | FileNotFoundError: [Errno 2] No such file or directory: 'data.txt' |
Angalia jina; tumia Path(__file__).parent / "data.txt"; hakikisha terminal iko folder sahihi (cd). |
| Kuandika kitu kisicho string | TypeError: write() argument must be str, not int |
f.write(str(namba)) au f-string. |
Kusoma file lililofunguliwa kwa "w" |
io.UnsupportedOperation: not readable |
Fungua kwa "r". |
Kusahau encoding (herufi za ajabu kama é) au UnicodeDecodeError: 'charmap' codec can't decode... |
— | Ongeza encoding="utf-8". |
Backslash kwenye Windows path: "C:\new\test.txt" (\n ni newline!) |
Path isiyo sahihi / OSError |
Tumia r"C:\new\test.txt", au /, au Path. |
Kutumia f nje ya with |
ValueError: I/O operation on closed file. |
Fanya kazi zote za file ndani ya block ya with. |
Zoezi darasani
Zoezi 1.1: Andika programu inayomwomba mtumiaji majina 3 (kwa input) na kuyahifadhi kwenye wanafunzi.txt, kila jina mstari wake.
Zoezi 1.2: Andika programu inayosoma wanafunzi.txt na kuchapisha idadi ya majina na jina refu zaidi.
Zoezi 1.3: Tengeneza "shajara" (diary): kila mara programu inapoendeshwa, inaomba ujumbe mmoja na kuuongeza mwishoni mwa shajara.txt pamoja na tarehe (tumia from datetime import date).
Jibu
# 1.1 with open("wanafunzi.txt", "w", encoding="utf-8") as f: for i in range(3): jina = input(f"Jina la mwanafunzi {i + 1}: ") f.write(jina + "\n") # 1.2 with open("wanafunzi.txt", encoding="utf-8") as f: majina = [mstari.strip() for mstari in f if mstari.strip()] # (Kama comprehension bado ni mpya, tumia loop ya kawaida na append) print("Idadi:", len(majina)) print("Jina refu zaidi:", max(majina, key=len)) # 1.3 from datetime import date from pathlib import Path shajara = Path(__file__).parent / "shajara.txt" ujumbe = input("Andika ujumbe wa leo: ") with open(shajara, "a", encoding="utf-8") as f: f.write(f"{date.today()}: {ujumbe}\n") print(shajara.read_text(encoding="utf-8"))
Kumbuka: max(..., key=len) ni mpya — kama mwanafunzi hajui, mwache atumie loop:
refu = "" for jina in majina: if len(jina) > len(refu): refu = jina
Kipindi 2 — CSV, JSON na Exceptions
Mtiririko wa kipindi
- Marudio ya kazi ya nyumbani (word counter)
- CSV:
csv.writer,csv.reader,DictWriter,DictReader - JSON:
dump/load,dumps/loads - Mapumziko
- Exceptions:
try/except/else/finally - Zoezi darasani
- Q&A + kazi ya nyumbani
Elezo kwa mwalimu (soma kwanza wewe)
CSV (Comma-Separated Values) ni file la maandishi lenye jedwali: kila mstari ni row, na safu (columns) zimetenganishwa na koma. Excel inaweza kulifungua. Kwa nini tusitumie split(",")? Kwa sababu thamani inaweza kuwa na koma ndani (mf. "Dar es Salaam, Tanzania") — module csv inashughulikia hilo kwa quotes.
Muhimu kwa Windows: fungua CSV kwa newline="" unapoandika, vinginevyo utapata mistari mitupu kati ya rows.
csv.writer(f)→writer.writerow([...]),writer.writerows([[...], [...]])csv.reader(f)→ kila row ni list ya strings (hata namba ni string! lazimaint()/float()).csv.DictWriter(f, fieldnames=[...])→writeheader(),writerow({...})csv.DictReader(f)→ kila row ni dict; mstari wa kwanza unatumika kama keys.
JSON (JavaScript Object Notation) ni format ya kuhifadhi data zenye muundo (dict, list) — inatumiwa na web APIs kila mahali. Ramani ya aina:
| Python | JSON |
|--------|------|
| dict | object {} |
| list, tuple | array [] |
| str | string (lazima " mbili) |
| int, float | number |
| True/False | true/false |
| None | null |
json.dump(data, f)— andika kwenye file.json.load(f)— soma kutoka file.json.dumps(data)— geuza kuwa string.json.loads(text)— string → Python.- (Kumbuka: "s" = string.) Tumia
indent=2kusoma kwa urahisi, naensure_ascii=Falsekuhifadhi herufi kama "é" moja kwa moja. - Keys za dict zinakuwa strings daima kwenye JSON:
{1: "a"}→{"1": "a"}. Set haiwezi kuwa JSON (TypeError).
Exceptions: Kosa linapotokea wakati programu inaendeshwa, Python "inarusha" (raises) exception. Isiposhikwa, programu inasimama na kuonyesha traceback. try/except inatuwezesha kuishika.
try: -> code inayoweza kuleta kosa except X: -> inaendeshwa kama kosa la aina X limetokea else: -> inaendeshwa kama HAKUNA kosa finally: -> inaendeshwa DAIMA (kosa au la) — kwa usafi (cleanup)
Kanuni: shika exception maalum (ValueError, FileNotFoundError), si except: tupu — hiyo inaficha bugs na hata Ctrl+C. except Exception as e: inakubalika kama kinga ya mwisho, ukichapisha e.
Exceptions za kawaida: ValueError (int("abc")), ZeroDivisionError, KeyError (d["haipo"]), IndexError, TypeError ("a" + 1), FileNotFoundError, json.JSONDecodeError (JSON mbovu; ni aina ya ValueError).
Sema hivi kwa mwanafunzi
- "CSV ni kama daftari la mahudhurio lenye mistari na safu. JSON ni kama fomu yenye sehemu zenye majina: 'Jina: ...', 'Umri: ...', na fomu ndani ya fomu."
- "
try/exceptni kama mlinda lango (goalkeeper). Unajaribu (try) kitu; mpira (kosa) ukija, goalkeeper (except) anaudaka badala ya kufungwa goli (programu kufa)." - "
finallyni kama kuzima taa unapotoka ofisini — unafanya hivyo kila siku, kazi iwe imeenda vizuri au vibaya." - "
elseni zawadi: inaendeshwa tu kama kila kitu kilienda salama."
Andika code hii live (share screen)
Hatua 1: CSV writer/reader — csv_demo.py
import csv wanafunzi = [ ["jina", "umri", "mji"], ["Asha", 17, "Arusha"], ["Baraka", 18, "Dar es Salaam, Kinondoni"], ["Neema", 16, "Mwanza"], ] with open("wanafunzi.csv", "w", newline="", encoding="utf-8") as f: writer = csv.writer(f) writer.writerows(wanafunzi) with open("wanafunzi.csv", newline="", encoding="utf-8") as f: reader = csv.reader(f) kichwa = next(reader) # ruka mstari wa kwanza (header) print("Header:", kichwa) for row in reader: print(row)
Output:
Header: ['jina', 'umri', 'mji'] ['Asha', '17', 'Arusha'] ['Baraka', '18', 'Dar es Salaam, Kinondoni'] ['Neema', '16', 'Mwanza']
Fungua wanafunzi.csv uonyeshe: Baraka,18,"Dar es Salaam, Kinondoni" — quotes zimeongezwa. Onyesha '17' ni string.
Hatua 2: DictReader na hesabu
import csv with open("wanafunzi.csv", newline="", encoding="utf-8") as f: reader = csv.DictReader(f) jumla = 0 idadi = 0 for row in reader: print(row["jina"], "anaishi", row["mji"]) jumla += int(row["umri"]) idadi += 1 print("Wastani wa umri:", jumla / idadi)
Output ya mwisho: Wastani wa umri: 17.0
Hatua 3: DictWriter
import csv bidhaa = [ {"jina": "Sukari", "bei": 3000, "idadi": 20}, {"jina": "Mchele", "bei": 2500, "idadi": 50}, ] with open("bidhaa.csv", "w", newline="", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=["jina", "bei", "idadi"]) writer.writeheader() writer.writerows(bidhaa)
Hatua 4: JSON — json_demo.py
import json mwanafunzi = { "jina": "Asha", "umri": 17, "masomo": ["Python", "Hisabati"], "amelipa": True, "simu": None, } with open("mwanafunzi.json", "w", encoding="utf-8") as f: json.dump(mwanafunzi, f, indent=2, ensure_ascii=False) with open("mwanafunzi.json", encoding="utf-8") as f: data = json.load(f) print(data["masomo"][0]) # Python print(type(data)) # <class 'dict'> maandishi = json.dumps(mwanafunzi) print(maandishi) print(type(maandishi)) # <class 'str'> nyuma = json.loads('{"a": 1, "b": [true, null]}') print(nyuma) # {'a': 1, 'b': [True, None]}
Fungua mwanafunzi.json uonyeshe true, null na quotes mbili.
Hatua 5: Exceptions — makosa_demo.py. Kwanza onyesha programu ikifa:
umri = int(input("Umri wako: ")) # andika "kumi"
ValueError: invalid literal for int() with base 10: 'kumi'. Fundisha kusoma traceback: soma mstari wa mwisho kwanza (aina ya kosa na ujumbe), kisha mstari wenye line N.
Kisha:
try: umri = int(input("Umri wako: ")) except ValueError: print("Tafadhali andika namba, mfano 17.") else: print(f"Mwakani utakuwa na miaka {umri + 1}.") finally: print("Asante kwa kutumia programu.")
Endesha mara mbili: 17 na kumi.
Hatua 6: Except nyingi na as e
def gawanya(): try: a = int(input("Namba ya kwanza: ")) b = int(input("Namba ya pili: ")) jibu = a / b except ValueError: print("Hiyo si namba.") except ZeroDivisionError as e: print("Huwezi kugawanya kwa sifuri:", e) else: print("Jibu:", jibu) gawanya()
Hatua 7: Loop mpaka mtumiaji aandike sahihi (pattern muhimu sana):
while True: try: namba = int(input("Andika namba kati ya 1 na 10: ")) break except ValueError: print("Si namba, jaribu tena.") print("Umeandika", namba)
Hatua 8: File + JSON + exception pamoja
import json from pathlib import Path faili = Path("mipangilio.json") try: with open(faili, encoding="utf-8") as f: mipangilio = json.load(f) except FileNotFoundError: print("Hakuna mipangilio, natumia default.") mipangilio = {"lugha": "sw", "rangi": "bluu"} except json.JSONDecodeError: print("File la JSON limeharibika!") mipangilio = {} print(mipangilio)
Onyesha: andika {lugha: sw (JSON mbovu) kwenye mipangilio.json kisha endesha tena → "File la JSON limeharibika!".
Maswali ya kumuuliza mwanafunzi
csv.readerinarudisha namba kama int au string? — String daima; lazima ugeuze.- Kwa nini
newline=""? — Kuzuia mistari mitupu kati ya rows kwenye Windows. - Tofauti ya
json.dumpnajson.dumps? —dumpinaandika kwenye file;dumpsinarudisha string. Trueya Python inakuwa nini kwenye JSON? —true.None→null.elsekwenyetryinaendeshwa lini? — Kama hakuna exception iliyotokea ndani yatry.finallyinaendeshwa lini? — Daima.- Kwa nini
except:tupu ni mbaya? — Inashika kila kitu, hata makosa ya kuandika code (bugs) na Ctrl+C, kwa hiyo hujui kilichoharibika.
Makosa ya kawaida
| Kosa | Ujumbe wa error | Suluhisho |
|---|---|---|
| Kusahau kugeuza string ya CSV | TypeError: unsupported operand type(s) for +=: 'int' and 'str' |
int(row["umri"]) |
| Key isiyo sahihi kwenye DictReader (mf. nafasi au herufi kubwa) | KeyError: 'Jina' |
Chapisha reader.fieldnames uone keys halisi. |
| Mistari mitupu kwenye CSV (Windows) | — | newline="" |
| Kuhifadhi set au object kwenye JSON | TypeError: Object of type set is not JSON serializable |
Geuza kuwa list: list(s). |
JSON yenye quotes moja {'a': 1} |
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes |
JSON inahitaji " mbili. |
json.load("file.json") (kupitisha jina badala ya file object) |
AttributeError: 'str' object has no attribute 'read' |
Fungua kwanza kwa with open(...) as f: json.load(f) |
except ValueError imewekwa lakini kosa ni ZeroDivisionError |
Programu bado inakufa | Ongeza except ya aina hiyo. |
Variable iliyoundwa ndani ya try inatumika baada ya kosa |
NameError: name 'umri' is not defined |
Itumie ndani ya else, au ipe thamani ya default kabla ya try. |
Zoezi darasani
Zoezi 2.1: Tengeneza alama.csv yenye columns jina,alama kwa wanafunzi 4 (kwa csv.writer). Kisha soma file na uchapishe aliyepata alama ya juu na wastani.
Zoezi 2.2: Andika function hifadhi_mawasiliano(jina, simu) inayoongeza mtu kwenye mawasiliano.json (dict ya jina → simu). Kama file halipo, ianze na dict tupu.
Zoezi 2.3: Andika programu inayouliza jina la file na kuchapisha idadi ya mistari. Kama file halipo, sema "File halipo" badala ya kufa.
Jibu
# 2.1 import csv with open("alama.csv", "w", newline="", encoding="utf-8") as f: w = csv.writer(f) w.writerow(["jina", "alama"]) w.writerows([["Asha", 88], ["Baraka", 74], ["Neema", 93], ["Juma", 65]]) bora_jina = None bora_alama = -1 jumla = 0 idadi = 0 with open("alama.csv", newline="", encoding="utf-8") as f: for row in csv.DictReader(f): alama = int(row["alama"]) jumla += alama idadi += 1 if alama > bora_alama: bora_alama = alama bora_jina = row["jina"] print(f"Bora: {bora_jina} ({bora_alama})") print(f"Wastani: {jumla / idadi:.1f}") # Bora: Neema (93) # Wastani: 80.0 # 2.2 import json from pathlib import Path FAILI = Path("mawasiliano.json") def hifadhi_mawasiliano(jina, simu): try: with open(FAILI, encoding="utf-8") as f: data = json.load(f) except FileNotFoundError: data = {} data[jina] = simu with open(FAILI, "w", encoding="utf-8") as f: json.dump(data, f, indent=2, ensure_ascii=False) hifadhi_mawasiliano("Asha", "0712345678") hifadhi_mawasiliano("Juma", "0755111222") print(FAILI.read_text(encoding="utf-8")) # 2.3 jina = input("Jina la file: ") try: with open(jina, encoding="utf-8") as f: mistari = f.readlines() except FileNotFoundError: print("File halipo") else: print("Idadi ya mistari:", len(mistari))
Kipindi 3 — raise, Custom Exceptions, venv na pip
Mtiririko wa kipindi
- Marudio ya kazi ya nyumbani (CSV/JSON)
raisena custom exceptions- Virtual environment: kwa nini,
python -m venv, activate, execution policy - Mapumziko
pip install,pip list,pip freeze > requirements.txt,pip install -r- Zoezi darasani (mradi mdogo: kitabu cha matumizi + package
rich) - Q&A + kazi ya nyumbani + muhtasari wa wiki
Elezo kwa mwalimu (soma kwanza wewe)
raise: Mpaka sasa Python ndiyo imekuwa ikirusha exceptions. Sisi pia tunaweza: raise ValueError("Umri hauwezi kuwa hasi"). Hii ni njia ya function kusema "nimepewa data mbaya, siwezi kuendelea" — badala ya kurudisha thamani ya ajabu kimya kimya. Anayeita function ndiye anayeamua kufanya nini (kwa try/except).
Custom exceptions: tunatengeneza aina yetu ya kosa kwa kurithi (inherit) kutoka Exception:
class SalioHalitoshi(Exception): pass
(Mwanafunzi bado hajasoma classes — Wiki 6! Sema tu: "hii ni namna ya kutengeneza aina mpya ya kosa; tutaelewa class kikamilifu wiki ijayo." Ni sawa kuitumia kama "template".) Faida: tunaweza kushika makosa yetu tu, bila kuchanganya na ValueError za kawaida.
raise bila kitu ndani ya except inarusha tena kosa lile lile (re-raise). raise NewError(...) from e inaunganisha makosa — taja tu kwa ufupi.
Virtual environment (venv): Ni folder lenye "nakala binafsi" ya Python na packages kwa ajili ya mradi mmoja. Kwa nini? Mradi A unahitaji requests 2.28, mradi B unahitaji requests 2.32. Bila venv, packages zote zinasakinishwa sehemu moja (global) na zinagongana. Kila mradi → venv yake.
Hatua kwenye PowerShell (ndani ya folder la mradi):
python -m venv .venv # tengeneza venv kwenye folder .venv .\.venv\Scripts\Activate.ps1 # activate
Baada ya kuactivate, prompt inaanza na (.venv). Sasa python na pip ni za venv. deactivate kutoka.
Tatizo maarufu la Windows: kuactivate kunaweza kuleta:
.\.venv\Scripts\Activate.ps1 : File C:\...\Activate.ps1 cannot be loaded because running scripts is disabled on this system.
Hii ni kwa sababu PowerShell kwa default inazuia scripts. Suluhisho (mara moja tu, kwa user wako, haihitaji Administrator):
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Jibu Y ikiuliza. Njia mbadala ya muda (kwa terminal hii tu): Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process.
VS Code: baada ya kutengeneza .venv, bonyeza Ctrl+Shift+P → "Python: Select Interpreter" → chagua ile yenye .venv. Terminal mpya za VS Code zitaactivate venv zenyewe.
pip ni program ya kusakinisha packages kutoka PyPI (pypi.org). Tumia python -m pip ... — inahakikisha pip ni ya Python unayoitumia.
python -m pip install rich— sakinishapython -m pip list— orodhapython -m pip show rich— taarifapython -m pip uninstall richpython -m pip freeze > requirements.txt— hifadhi orodha ya packages na versionspython -m pip install -r requirements.txt— sakinisha zote (mf. kwenye kompyuta nyingine)
Kumbuka: kwenye PowerShell ya Windows 5.1, > inaandika file kwa UTF-16, ambalo pip install -r bado inasoma vizuri kwenye matoleo mapya; lakini kama kuna tatizo, tumia python -m pip freeze | Out-File -Encoding utf8 requirements.txt.
Folder .venv halitumwi kwa wengine wala kwenye GitHub (Wiki 8: .gitignore); tunatuma requirements.txt tu.
Sema hivi kwa mwanafunzi
- "
raiseni kama mwamuzi kupiga filimbi: 'Faulo! Mchezo usimame.' Function inasema 'data hii si sahihi!'" - "Custom exception ni kama kutengeneza kadi yako mwenyewe — si 'kadi ya njano' ya kawaida bali 'kadi ya SalioHalitoshi'. Unaweza kuidaka hiyo hasa."
- "Virtual environment ni kama sanduku la vifaa la kila fundi. Fundi wa umeme na fundi wa bomba hawachanganyi vifaa vyao. Kila mradi una sanduku lake."
- "
requirements.txtni kama orodha ya manunuzi: unampa mtu orodha, si duka zima. Yeye ananunua (pip install -r) mwenyewe."
Andika code hii live (share screen)
Hatua 1: raise — raise_demo.py
def weka_umri(umri): if not isinstance(umri, int): raise TypeError("Umri lazima uwe namba kamili (int).") if umri < 0 or umri > 130: raise ValueError(f"Umri {umri} si sahihi.") return umri print(weka_umri(20)) try: weka_umri(-5) except ValueError as e: print("Kosa:", e) try: weka_umri("ishirini") except TypeError as e: print("Kosa:", e)
Output:
20 Kosa: Umri -5 si sahihi. Kosa: Umri lazima uwe namba kamili (int).
Hatua 2: Custom exception — benki_mini.py
class SalioHalitoshi(Exception): """Inarushwa pale mtu anapotoa pesa zaidi ya salio.""" pass class KiasiSiSahihi(Exception): pass def toa_pesa(salio, kiasi): if kiasi <= 0: raise KiasiSiSahihi("Kiasi lazima kiwe zaidi ya sifuri.") if kiasi > salio: raise SalioHalitoshi(f"Salio ni {salio}, umeomba {kiasi}.") return salio - kiasi salio = 10_000 for ombi in [3_000, 20_000, -50]: try: salio = toa_pesa(salio, ombi) except SalioHalitoshi as e: print("Samahani:", e) except KiasiSiSahihi as e: print("Kosa:", e) else: print(f"Umetoa {ombi}. Salio jipya: {salio}")
Output:
Umetoa 3000. Salio jipya: 7000 Samahani: Salio ni 7000, umeomba 20000. Kosa: Kiasi lazima kiwe zaidi ya sifuri.
Eleza 10_000 — underscore ni kwa kusoma rahisi tu, ni sawa na 10000.
Hatua 3: venv — kwenye terminal ya VS Code (PowerShell). Tengeneza folder jipya:
mkdir mradi_venv cd mradi_venv python -m venv .venv .\.venv\Scripts\Activate.ps1
Kama kosa la "running scripts is disabled" litatokea — hii ni nafasi nzuri ya kufundisha:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser .\.venv\Scripts\Activate.ps1
Thibitisha:
python -c "import sys; print(sys.prefix)"
Output inapaswa kuishia na ...\mradi_venv\.venv. Linganisha baada ya deactivate — itaonyesha folder la Python ya global.
Hatua 4: pip
python -m pip install rich python -m pip list python -m pip freeze > requirements.txt Get-Content requirements.txt
requirements.txt itakuwa na kitu kama:
markdown-it-py==4.0.0 mdurl==0.1.2 Pygments==2.19.2 rich==14.2.0
(Versions zinaweza kutofautiana — si tatizo.) Eleza: rich inahitaji packages nyingine (dependencies), ndio maana ziko nne.
Tengeneza rangi.py ndani ya mradi_venv:
from rich import print from rich.table import Table print("[bold green]Habari![/bold green] Karibu kwenye [red]Python[/red].") jedwali = Table(title="Wanafunzi") jedwali.add_column("Jina") jedwali.add_column("Alama", justify="right") jedwali.add_row("Asha", "88") jedwali.add_row("Baraka", "74") print(jedwali)
Endesha python rangi.py. Kisha deactivate na endesha tena → ModuleNotFoundError: No module named 'rich' (kama rich haiko global). Hii inathibitisha venv inafanya kazi.
Hatua 5: Kuunda upya mazingira (kuiga kompyuta nyingine):
deactivate Remove-Item -Recurse -Force .venv python -m venv .venv .\.venv\Scripts\Activate.ps1 python -m pip install -r requirements.txt python rangi.py
Maswali ya kumuuliza mwanafunzi
- Kwa nini function itumie
raisebadala yaprint("kosa")? — Print haisimamishi programu wala haimjulishi anayeita;raiseinamlazimisha anayeita kushughulikia kosa. - Custom exception inarithi kutoka wapi? —
Exception. - Utajuaje venv iko active? — Prompt ina
(.venv)mwanzoni;sys.prefixinaonyesha folder la venv. - Kwa nini tusitume folder
.venvkwa rafiki? — Ni kubwa, lina paths za kompyuta yako; anatengeneza lake kwarequirements.txt. - Amri gani inasakinisha packages zote kutoka requirements.txt? —
python -m pip install -r requirements.txt - Kosa la "running scripts is disabled" linatatuliwaje? —
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Makosa ya kawaida
| Kosa | Ujumbe wa error | Suluhisho |
|---|---|---|
| Execution policy | Activate.ps1 cannot be loaded because running scripts is disabled on this system |
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser |
Kuandika source .venv/bin/activate (amri ya Linux/Mac) |
source : The term 'source' is not recognized... |
Windows: .\.venv\Scripts\Activate.ps1 |
| Kusakinisha bila kuactivate venv | Package inaenda global; ndani ya venv ModuleNotFoundError |
Activate kwanza, kisha python -m pip install. |
| VS Code inatumia interpreter tofauti | Import "rich" could not be resolved (mstari wa njano) |
Ctrl+Shift+P → Python: Select Interpreter → .venv |
pip haitambuliki |
pip : The term 'pip' is not recognized... |
Tumia python -m pip |
Kuita file lako json.py au csv.py |
AttributeError: module 'json' has no attribute 'dump' |
Badilisha jina la file lako; futa __pycache__. |
raise "kosa" (string) |
TypeError: exceptions must derive from BaseException |
raise ValueError("kosa") |
Zoezi darasani
Zoezi 3.1: Andika function angalia_alama(alama) inayorusha ValueError kama alama si kati ya 0 na 100, vinginevyo inarudisha grade ("A" ≥ 80, "B" ≥ 65, "C" ≥ 50, "F" vinginevyo). Ijaribu kwa 85, 105, 40.
Zoezi 3.2: Tengeneza custom exception BidhaaHaipo. Andika function bei_ya(bidhaa, orodha) inayorusha BidhaaHaipo kama bidhaa haiko kwenye dict ya bei.
Zoezi 3.3 (venv): Tengeneza folder matumizi, venv ndani yake, sakinisha rich, tengeneza requirements.txt. Andika programu matumizi.py inayosoma matumizi.csv (columns kitu,kiasi) na kuonyesha jedwali la rich pamoja na jumla. Kama mstari una kiasi kisicho namba, iruke na kuonyesha onyo.
Jibu
# 3.1 def angalia_alama(alama): if not 0 <= alama <= 100: raise ValueError(f"Alama {alama} lazima iwe kati ya 0 na 100.") if alama >= 80: return "A" elif alama >= 65: return "B" elif alama >= 50: return "C" return "F" for a in [85, 105, 40]: try: print(a, "->", angalia_alama(a)) except ValueError as e: print("Kosa:", e) # 85 -> A # Kosa: Alama 105 lazima iwe kati ya 0 na 100. # 40 -> F # 3.2 class BidhaaHaipo(Exception): pass def bei_ya(bidhaa, orodha): if bidhaa not in orodha: raise BidhaaHaipo(f"'{bidhaa}' haipo dukani.") return orodha[bidhaa] bei = {"sukari": 3000, "chumvi": 800} try: print(bei_ya("sukari", bei)) print(bei_ya("unga", bei)) except BidhaaHaipo as e: print("Kosa:", e) # 3000 # Kosa: 'unga' haipo dukani.
3.3 — amri za PowerShell:
mkdir matumizi; cd matumizi python -m venv .venv .\.venv\Scripts\Activate.ps1 python -m pip install rich python -m pip freeze > requirements.txt
matumizi.csv:
kitu,kiasi nauli,2000 chakula,5000 vocha,abc maji,1000
matumizi.py:
import csv from pathlib import Path from rich import print from rich.table import Table faili = Path(__file__).parent / "matumizi.csv" jedwali = Table(title="Matumizi ya Leo") jedwali.add_column("Kitu") jedwali.add_column("Kiasi (TSh)", justify="right") jumla = 0 try: with open(faili, newline="", encoding="utf-8") as f: for row in csv.DictReader(f): try: kiasi = int(row["kiasi"]) except ValueError: print(f"[yellow]Onyo:[/yellow] '{row['kiasi']}' si namba, nimeruka '{row['kitu']}'.") continue jumla += kiasi jedwali.add_row(row["kitu"], f"{kiasi:,}") except FileNotFoundError: print("[red]matumizi.csv halipo![/red]") else: jedwali.add_row("[bold]JUMLA[/bold]", f"[bold]{jumla:,}[/bold]") print(jedwali)
Kazi ya Nyumbani
(Inatakiwa: kipindi kijacho)
Kazi 1 — Word counter (baada ya Kipindi 1): Andika programu inayosoma file la maandishi (hadithi.txt — mwanafunzi aandike aya 2–3 za Kiswahili) na kuchapisha: idadi ya mistari, idadi ya maneno, na neno lililotumika mara nyingi zaidi (bila kujali herufi kubwa/ndogo).
Kazi 2 — Daftari la alama (baada ya Kipindi 2): Programu yenye menu: 1. Ongeza mwanafunzi, 2. Onyesha wote, 3. Toka. Data ihifadhiwe kwenye alama.json (list ya dicts {"jina":..., "alama":...}) ili isipotee programu ikifungwa. Alama isiyo namba isilete crash.
Kazi 3 — Hamisha (baada ya Kipindi 3): Andika function json_kwenda_csv(json_path, csv_path) inayogeuza alama.json ya Kazi 2 kuwa alama.csv. Rusha custom exception FailiTupu kama JSON ina list tupu. Weka kazi zote ndani ya folder lenye .venv na requirements.txt (hata kama ni tupu).
Jibu
# Kazi 1 from pathlib import Path maandishi = Path("hadithi.txt").read_text(encoding="utf-8") mistari = maandishi.splitlines() maneno = maandishi.lower().split() hesabu = {} for neno in maneno: neno = neno.strip(".,!?;:\"'()") if neno: hesabu[neno] = hesabu.get(neno, 0) + 1 print("Mistari:", len(mistari)) print("Maneno:", len(maneno)) if hesabu: neno_bora = max(hesabu, key=hesabu.get) print(f"Neno linalorudiwa zaidi: '{neno_bora}' mara {hesabu[neno_bora]}")
# Kazi 2 import json from pathlib import Path FAILI = Path(__file__).parent / "alama.json" def pakia(): try: with open(FAILI, encoding="utf-8") as f: return json.load(f) except (FileNotFoundError, json.JSONDecodeError): return [] def hifadhi(wanafunzi): with open(FAILI, "w", encoding="utf-8") as f: json.dump(wanafunzi, f, indent=2, ensure_ascii=False) wanafunzi = pakia() while True: print("\n1. Ongeza mwanafunzi\n2. Onyesha wote\n3. Toka") chaguo = input("Chagua: ") if chaguo == "1": jina = input("Jina: ").strip() try: alama = int(input("Alama: ")) except ValueError: print("Alama lazima iwe namba.") continue wanafunzi.append({"jina": jina, "alama": alama}) hifadhi(wanafunzi) print("Imehifadhiwa.") elif chaguo == "2": if not wanafunzi: print("Hakuna mwanafunzi bado.") for w in wanafunzi: print(f"{w['jina']:<15}{w['alama']:>5}") elif chaguo == "3": print("Kwaheri!") break else: print("Chaguo si sahihi.")
# Kazi 3 import csv import json class FailiTupu(Exception): pass def json_kwenda_csv(json_path, csv_path): with open(json_path, encoding="utf-8") as f: data = json.load(f) if not data: raise FailiTupu(f"{json_path} haina data.") with open(csv_path, "w", newline="", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=["jina", "alama"]) writer.writeheader() writer.writerows(data) return len(data) try: n = json_kwenda_csv("alama.json", "alama.csv") print(f"Nimehamisha wanafunzi {n}.") except FileNotFoundError: print("alama.json halipo.") except FailiTupu as e: print("Kosa:", e)
Ukiulizwa swali usilolijua
- Sema kwa uaminifu: "Swali zuri — ngoja tulichunguze pamoja," kisha jaribu kwenye terminal (
pythonREPL) au tafuta: "pythonsite:docs.python.org" au Stack Overflow. Unaweza pia kuandika help(open)auhelp(json.dump)kwenye REPL. - Docs: files https://docs.python.org/3/tutorial/inputoutput.html |
csvhttps://docs.python.org/3/library/csv.html |jsonhttps://docs.python.org/3/library/json.html |pathlibhttps://docs.python.org/3/library/pathlib.html | exceptions https://docs.python.org/3/library/exceptions.html | venv https://docs.python.org/3/library/venv.html | pip https://pip.pypa.io/en/stable/user_guide/ - Kama hukupata jibu darasani, liandike na ulijibu mwanzoni mwa kipindi kijacho.
Checklist ya mwisho wa wiki
- Anaeleza tofauti ya
"r","w","a"bila kuangalia notes. - Anatumia
with open(..., encoding="utf-8")kwa mazoea. - Anasoma file mstari kwa mstari na kutumia
.strip(). - Anatumia
Path(__file__).parent / "jina"naexists(). - Anasoma/kuandika CSV kwa
DictReader/DictWriterna anakumbukanewline="". - Anahifadhi na kusoma dict/list kwa JSON.
- Anaandika
try/except/else/finallyna kushika exception maalum. - Anasoma traceback (mstari wa mwisho kwanza).
- Anatumia
raisena kutengeneza custom exception. - Anatengeneza na kuactivate
.venvkwenye PowerShell bila msaada. - Anatumia
pip install,pip freeze > requirements.txt,pip install -r. - Kazi ya nyumbani ya Wiki 5 imekabidhiwa.