Edukira joan

PYTHON liburua/Sarrera/Irteera. Internet

Wikibookstik

7. Sarrera/irteera. Internet

[aldatu]

Aurreko kapituluetan erabili ditugun input eta print funtzioek osatzen dute sarrera/irteera egiteko oinarri-oinarrizko bidea, baina programa konplexuagoak egin ahala ahalmen handiagoa behar dugu Sarrera/Irteerari (S/I) begira: mezuetan formatu aberatsagoak erabiltzea, diskoko fitxategiekin lan egitea, zuzeneko atzipena eta datu-baseak erabiltzea, Interneteko datuak prozesatzea...

Beraz, kapitulu honetan horri helduko diogu ordena honetan: mezuei formatua ematea, fitxategien kudeaketa eta atzipena, eta Interneteko datuen maneiua.

7.1. MEZUEN FORMATUA

[aldatu]

Programek idatzi behar dituzten mezuetan informazioa era egituratuago eta ikusgarriagoan erakutsi ahal izateko bi bide nagusi daude: % sinboloan oinarritzen den print funtzioa (modu zaharra), eta format metodoa. Bigarrena da lehenesten dena, baina lehenengoa da bertsio zaharragoetatik datorrena (eta beste zenbait lengoaiatatik datozen programatzaileei errazen egiten zaiena).

7.1.1. Modu zaharra

[aldatu]

Beste lengoaietako printf funtzioaren antzekoa da modu hau. Lehen eremuan konstanteak eta aldagaien zein espresioen formatuak zehazten dira, gero % karakterea eta azkenik aldagaiak zein espresioak parentesi artean.

7.1. taulan ikus daitekeenez, formatua adierazteko % karakterea eta letra bat zehazten da. Letraren aurretik zenbaki bat gehi daiteke luzera adierazteko, eta zenbaki errealen kasuan bi zenbaki puntu hamartarrez bereizita.

7.1. taula. print funtzioan formatuak adierazteko hainbat kode:
ADIBIDEA ESANAHIA
%s string
%d zenbaki hamartarra
%f zenbaki erreala (puntu dezimala agertuko da)
%b formatu bitarra
%X formatu hamaseitarra
%E Formatu esponentziala
%4d zenbaki hamartarra 4 digiturekin
%.2f zenbaki erreala, bi zifra puntu ondoren
%5.1f zenbaki erreala, bost zifra puntu aurretik eta bat puntu ondoren

Modu hau erabiltzen duen eta 2.3. programaren aldaera den kodea agertzen da 7.1. programan.

7.1a. programa. Inprimaketa formatudunaren adibidea:

PI = 3.14159
# irakurketa eta bihurketa
r = float(input("sakatu erradioaren neurria: "))
perimetroa = 2 * PI * r
azalera = PI * r * r
# idazketa
formatua = "%d erradioari dagokion azalera %.2f da eta perimetroa %.2f."
print (formatua % (r, azalera, perimetroa))

##>>>
##sakatu erradioaren neurria: 1
##1.00 erradioari dagokion azalera 3.14 da eta perimetroa 6.28.

7.1.2. format metodoa

[aldatu]

Edozein karaktere-kateren gainean aplikatzen da, baina S/Irekin oso lotuta dago.

Adibide batekin hasiko gara, 2.2. programaren bilakaera dena:

izena = input("Sartu zure izena: ") # sarrera
print("Kaixo {}".format(izena)) 		# irteera format erabilita)

##>>>
##Sartu zure izena: Koldo
##Kaixo Koldo

2.2. programarekin konparatuta, kasu honetan giltzak erabili dira stringean eta aldagaiaren izena format metodoaren parametro gisa. Adibide honetarako aldrebesa ematen badu ere, format metodoa erabiltzea oso ahaltsua da aldagai anitzen balioa jaso behar duten mezuetarako. Adibidez 2.3. programaren aldaera 7.1b. programan agertzen da, idazketa lerro bakar batera ekarriz eta formatua dotoretuz.

7.1b. programa. Inprimaketa formatudunaren adibidea:

PI = 3.14159
# irakurketa eta bihurketa
r = float(input("sakatu erradioaren neurria: "))
perimetroa = 2 * PI * r
azalera = PI * r * r
# idazketa
mezu = "{:.2f} erradioari dagokion azalera {:.2f} da eta perimetroa {:.2f}."
print (mezu.format(r, azalera, perimetroa))

##>>>
##sakatu erradioaren neurria: 1
##1.00 erradioari dagokion azalera 3.14 da eta perimetroa 6.28.

Kasu honetan, sententziak laburtu eta irakurgarritasuna handitze aldera, mezu izeneko katea definitu da tarteko aldagai gisa.

Beraz, formatua adierazten duen karaktere-kate baten gainean aplikatzen da format metodoa, katean agertzen diren giltzak ordezkatzen ditu bere parametroen balioekin (emandako ordena berean).

Dena den, oraindik hobekuntzak egin daitezke, adibidez balio errealen zifra kopurua mugatzea. Programa probatu baldin baduzu, azalera edo perimetroa dezimal askorekin agertzen dira (erradioa 6 denean 113.09723999999999 agertzen da adibidez). Hori mugatzeko, bi dezimalera adibidez, giltzen artean :.2f zehatz daiteke, azken aurreko lerroa honela geratuko litzakeela:

mezu = "{:.2f} erradioari dagokion azalera {:.2f} da eta perimetroa {:.2f}."

Kasu horretan .2f espresioak adierazten du zenbaki errealari bi zifra dezimal dagozkiola. Bi puntu karakterea formatua adierazteko eransten da, eta formatuaren atal asko zehatz daitezke: doiketa (ezkerrean, eskuinean, erdian), zeinua eta dezimalak... 7.2. taulan ikus daitezke bihurketa-karaktere ohikoenak. Kodea beti ':' karakterearen ondoan agertuko da eta hainbat kasutan zenbakiak (aurreko programan 2 adib.) edo konstanteak (% portzentajeak adierazteko esaterako) txerta daitezke.

7.2. taula. Formatuak adierazteko hainbat kode:
KODEA ESANAHIA
s string (ezer ez jartzearen baliokidea)
d zenbaki hamartarra (zenbaki osoetarako)
n zenbaki errealak (puntu dezimala agertuko da)
b formatu bitarra
X formatu hamaseitarra
< doituta ezkerrera
> doituta eskuinera
^ doituta erdira
, zenbakietan milakoen mugak txertatzeko

7.2. programan beste adibide bat azter daiteke, 1 eta 15 zenbakien arteko balioak hamartarrez, bitarrez eta hamaseitarrez inprimatzen duen programa.

7.2. programa. Inprimaketa formatudunaren bigarren adibidea:

mezu="zenb: {:2d} bitarrez: {:5b} hamaseitarrez {:2X}"
for n in range(1,16):
	print(mezu.format(n, n, n))

Hau da exekuzioaren emaitza:

zenb:  1 bitarrez:     1 hamaseitarrez  1
zenb:  2 bitarrez:    10 hamaseitarrez  2
zenb:  3 bitarrez:    11 hamaseitarrez  3
zenb:  4 bitarrez:   100 hamaseitarrez  4
zenb:  5 bitarrez:   101 hamaseitarrez  5
zenb:  6 bitarrez:   110 hamaseitarrez  6
zenb:  7 bitarrez:   111 hamaseitarrez  7
zenb:  8 bitarrez:  1000 hamaseitarrez  8
zenb:  9 bitarrez:  1001 hamaseitarrez  9
zenb: 10 bitarrez:  1010 hamaseitarrez  A
zenb: 11 bitarrez:  1011 hamaseitarrez  B
zenb: 12 bitarrez:  1100 hamaseitarrez  C
zenb: 13 bitarrez:  1101 hamaseitarrez  D
zenb: 14 bitarrez:  1110 hamaseitarrez  E
zenb: 15 bitarrez:  1111 hamaseitarrez  F

https://docs.python.org/3/library/string.html webgunean formateatzearen inguruko informazio osatuagoa aurki daiteke.

locals funtzioa (**locals() erabili behar da.) ere erabil daiteke formatua emateko. Hiztegietarako pentsatuta dago, baina aldagaien izenak ere hiztegi moduan erregistratzen direnez, aldagaien izenak giltzen artean ere jar daitezke. 7.3. programan 7.1. programaren aldaera bat agertzen da. Ohar zaitez '\' karakterearen erabileraz ere, stringa hurrengo lerroan jarraitzen duela adierazteko erabiltzen baita.

PI = 3.14159
# irakurketa eta bihurketa
r = float(input("sakatu erradioaren neurria: "))
perimetroa = 2 * PI * r
azalera = PI * r * r
# idazketa
mezu = "{r:.2f} erradioari dagokion azalera {azalera:.2f} \
da eta perimetroa {perimetroa:.2f}."
print (mezu.format(**locals()))

Agian hauxe intuitiboagoa da, baina gustukoen duzuna erabil dezakezu.

7.2. FITXATEGIAK

[aldatu]

Fitxategiak erabiltzeko hainbat funtzio eta metodo erabiliko dira. Ohi bezala, adibide sinple batekin hasiko gara, 7.4. programarekin, hain zuzen ere.

Hasteko ikusiko ditugu zeintzuk diren Colab fitxategi-sisteman kapitulu honetan eskura ditugun fitxategiak.

import os
print("Karpeta honetako fitxategiak:\n", sst_home)

for karp, azpik, fitxategiak in os.walk(sst_home):
    print(karp)
    for fitx in fitxategiak:
        print(fitx)

Hau da emaitza:

Karpeta honetako fitxategiak:
 drive/My Drive/Colab Notebooks/Python_UEU_20/kodea_izen_luzeak/kap7_sarrera_irteera_Internet/
drive/My Drive/Colab Notebooks/Python_UEU_20/kodea_izen_luzeak/kap7_sarrera_irteera_Internet/
p7-2_format_2.py
p7-5_oihartzuna.py
p7-6b_fitx_kateaketa.py
p7-8_zuzeneko_atzipena.py
proba_seek
p7-6c_fitx_kateaketa.py
p7-9_web.py
p7-10_mezua_bidali.py
p7-11_hitz_maiztasuna.py
p7-3_format_locals.py
p7-1_format_1b.py
p7-1_format_1.py
p7-4_fitxategia_lerroka.py
p7-4b_fitxategia_lerroka.py
p7-7_string_bilatu_fitx.py
p7-6_fitx_kateaketa.py
p7-12_zuhaitz_bitarra.py

Hori ikusita, fitxategiak erabiltzeko hainbat funtzio eta metodo erabiliko dira. Ohi bezala, adibide sinple batekin hasiko gara, 7.4. programarekin, hain zuzen ere. Kontuz, lehenengo bertsio bat da, geroago 7.4b. programan hobetuko dugun

7.4. programa. Fitxategi baten irakurketa lerroz lerro:

# programaren fitxategia inprimatzea (lerroz lerro)

#for lerro in open('p7-4.py','r').readlines():
for lerro in open(sst_home + 'p7-4_fitxategia_lerroka.py','r').readlines():
    print(lerro)

open funtzioa erabili da eta itzultzen duen objektuaren gainean readlines metodoa (ez da derrigorrezkoa readlines metodoa erabiltzea, baina lerroz lerro irakurri nahi badugu, erabiliko da). Oso kode trinkoa eta irakurterraza lortzen da. open funtzioak itzultzen duen objektuaren gainean (file), geroago aipatuko diren metodo guztiak izango dira aplikagarri.

Hala ere, aurreko soluzioak hiru eragozpen txiki edukitzen ditu:

  • fitxategia itxi gabe geratzen dela,
  • lerro-bukaerako karakterea ez dela kentzen, eta
  • utf-8 estandarraren erabilera ez dela ziurtatzen.

Batetik, ez da larria, baina fitxategiak ixtea komenigarria da, baliabideak ondo kudeatzeko. Kudeaketa ona bideratzeko with .. as egitura sortu zuten fitxategietarako eta beste egituretarako). Haren bitartez objektu bat sortzen da, kudeaketa errazteaz gain automatikoki itxiko dena.

Beste alde batetik, splitlines metodoak errazten du lerroz-lerroko tratamendua. Testu-fitxategiko testua lerrotan banatu eta lerro-bukaerako karaktereak ezabatzen ditu.

Azkenik, utf-8 estandarra erabiltzen dela ziurtatzea komeni da beti fitxategia erabltzerakoan open metodoan encoding parametroan 'utf-8' balioa jarrita.

Hiru eragozpen horiek gainditu ahal izateko 7.4b. programan ikus daiteke testu-fitxategi baten lerroz-lerroko irakurketarako programa eredu bat .

7.4b. programa. Fitxategi baten irakurketa lerroz lerro:

with open(sst_home + 'p7-4b_fitxategia_lerroka.py', encoding='utf-8') as fitx:
  lerroak = fitx.read().splitlines()
  for lerro in lerroak:
    print(lerro)

io izeneko moduluan daude fitxategiekin lotutako funtzioa eta metodoak. Modulu honek oinarrizko funtzionalitate guztiak eskaintzen ditu, fitxategiak Unix munduan ohikoa den datu-fluxu bihurtuta file objektuaren bitartez. Irakurtzen edo idazten den karaktere-kate bat bezala ikusten baita sarrera/irteerako edozein objektu.

Beste lengoaietan bezala, fitxategi bat erabiltzeko fitxategi hori ireki egin behar da, dagokion kontrol-informazioa memorian karga dadin eta sistema eragilearen sarrera/irteerako oinarrizko funtzioek kontsulta dezaten. Kontrol-informazio hori file motako egitura batean metatzen da fitxategia irekitzen denean, bere gainean sarrera/irteerako metodoak aplikatu ahal izateko.

Beraz, objektua eskuratzeko open funtzioa erabiliko da. Prototipoa ondokoa da: f = open("fitxategia", "modua", encoding="utf-8") Kodeketa (encoding) hautazkoa da, baina testu-fitxategien kasuan garrantzitsua da ondo zehaztea. Bestalde, beste parametro batzuk ere zehatz daitezke: errors (erroreen maneiurako), newline (lerro-bukaeraren maneiurako) eta closefd (itxiera kontrolatzeko).

Fitxategien artean bi mota nagusi bereizten dira: testukoak eta bitarrak. Bigarren motakoetan b letra adieraziko da motaren barruan. Fitxategiak bitarrak definituz gero, sistema eragileak ez du aipatutako byteen eta lerroen interpretazio berezirik egingo. Bitak irakurri edo idatziko dira azaltzen diren eran. Fitxategi bitarrak testuak ez diren datuak gordetzeko eta fitxategiaren edukia dagoen bezala mantentzeko erabiliko dira. Motaren arabera, metodoen semantika apur bat alda daiteke edo metodo berriak agertu, baina ezaugarri nagusiak komunak dira eta horiek izango dira hemen azalduko direnak. Metodoaren line edo lines agertzen bada testu-fitxategietan aplikatzeko direla ulertu behar da.

Irekitzeko ohiko moduak 7.2. taulan jasota daude.

7.2. taula. Irekitzeko moduak: KODEA ESANAHIA

7.2. taula. Irekitzeko moduak:
KODEA ESANAHIA
r Testu-fitxategi bat irakurtzeko
w Testu-fitxategi batean idazteko
a Testu-fitxategi batean idazteko baina gehiketak eginez
+ Testu-fitxategi bat eguneratzeko (irakurri zein idatzi)
b Formatu bitarra (aurrekoekin konbina daiteke). rb, wb, ab...

Normalean, eraginkortasunari begira, fitxategiak memorian islatzen dira tarte batez (buffering), baina open funtzioan buffering=0 aukeraz galaraz daiteke hori.

S/I estandarra (teklatua eta pantaila normalean, komando-lerrotik birbideratzeko aukera ahaztu gabe) erabiltzeko sys.stdin, sys.stdout eta sys.stderr fluxuak erabil daitezke (sys modulua inportatuz) irekitzeko beharrik gabe. 7.4. programan oinarrituta oihartzuna lortzeko programa idaztea erraza da, beraz (ikus 7.5. programa).

7.5. programa. Oihartzun funtzioa:

import sys
for lerro in sys.stdin:
  print(lerro)

7.6. programan sarrera/irteerako funtzioak eta metodoak erabiltzen dira, UNIXen erabiltzen den cat izeneko programa inplementatzeko. Programa horren bidez parametro gisa zehazten diren fitxategiak idazten dira bata bestearen atzean irteera estandarrean.

7.6. programa. Hainbat fitxategi kateatzea:

import sys

def erantsi_fitxat (fitx):
	for sarr in fitx:		#	for sarr in fitx.read():
		sys.stdout.writelines(sarr)

for arg in sys.argv[1:]:
	f = open(arg,'r')
	erantsi_fitxat (f)

Proba ezazu parametro gisa bi programen izenak zehaztuta.

Fitxategietako datuak bata bestearen ondoren jarraian tratatu ohi dira, atzipen sekuentziala eginez, eta horixe da orain arte azaldu dena. Datuak bata bestearen ondoren tratatu nahi ez direnean, zuzeneko atzipena beharko da, seek eta tell metodoetan oinarrituta burutzen dena. Geroxeago azalduko ditugu.

7.2.1. Ohiko metodoak

[aldatu]

Ondoren io moduluaren ohiko metodoak azalduko dira, metodo bakoitzaren prototipoa eta deskribapena zehaztuz:

close()
flush()

objektuari dagokion fitxategia itxi eta objektua desagertzen da. Aurretik memorian zerbait balego oraindik idatzi gabe, fitxategian idatziko du itxi baino lehenago. flush() metodoak azken zeregin hori du.

read(tan=-1)
readall()

read metodoak zehaztutako tamaina (size) irakurtzen du, edo fitxategi osoa tamaina zehazten ez bada (-1). Irakurritakoa itzultzen du emaitza gisa. readall metodoak horixe egiten du, fitxategi osoa irakurri eta memoriara ekarri. Kontuz fitxategi handiekin!

readlines(kop=-1)
readline()

readlines metodoak aipatutako lerro kopurua (kop) irakurtzen du, edo fitxategi osoa, kopurua zehazten ez bada (-1). readline metodoak lerro bat irakurtzen du. Testu-fitxategietarako oso egokiak dira. Irakurritakoa itzultzen du karaktere-kate formatuan. Kontuan hartu behar da read/readline metodoak erabiliz fitxategien posizioa eguneratzen dela eta fitxategia berriro hasieratik atzitzeko berriro ireki beharko dela.

write(buf)
writelines(lerroak)

buf parametroak adierazten duen katea fitxategiaren barneko bufferrean idazten du write metodoak, geroxeago idatz dadin. writelines metodoak antzera lan egiten du, baina lerroz lerro lan eginez.

C lengoaiako scanf funtzioaren baliokiderik ez dago; horren ordez read eta aurreko kapituluan azaldutako split metodoa konbinatzea proposatzen da. Idazketa formatudunetan, berriz, aurretik azaldutako format metodoa eta write edo writelines konbinatzea da ohikoena.

Fitxategiaren bukaera (EOF) detektatzea ohikoa da fitxategi sekuentzialak erabiltzean. Pythonen ez da behar izango, fitxategi osoak eskuratzeko metodoak erabiltzen badira (readall, getlines, edo read metodoak parametrorik gabe), baina zatika edo lerroka irakurtzean (readline edo read luzera batekin) detektatu beharko da. Buffer hutsa jasotzen denean, fitxategi-bukaera antzeman dela suposatuko da halakoetan, beraz, ez dago metodo berezirik horretarako.

7.7. programan testu-editoreek duten bilaketa-laguntza nola programatzen den ikus daiteke. Lerroka irakurtzen da eta find metodoaren bidez (edo in eragilearen bidez) aztertzen da ea karaktere-katea lerroan dagoen ala ez (gogoratu find metodoak posizioa itzultzen duela edo -1 aurkitzen ez badu).

7.7. programa. string baten bilaketa fitxategi batean:

import sys

fitxat = sys.argv[1]
st = sys.argv[2]
n = 0
f = open(fitxat,'r')
for lerro in f.readlines():
	if st in lerro:
		print(lerro)
		n = n+1
print ("Agerpen kop.:",n)

7.2.2. Erroreen maneiua

[aldatu]
7.2.2.1 Exekuzio-erroreen maneiua
[aldatu]

Sarrera/irteerako metodo bakoitzak balio berezi bat itzuliko du, errore bat gertatzen bada. Erroreen tratamendurako io objektuaren hainbat eremu eta salbuespen erabil daitezke. S/Irako orokorrena IOError izeneko salbuespena erabiltzea da try eta except sententziekin batera (ikus aurreko kapituluan salbuespenei dagokien atala erabilera gogoratzeko). Fitxategiekin lotutako erroreak OSError multzoaren barruan sartzen dira, adibidez, fitxategiak irekitzean sortzen direnak (ohikoa da fitxategia ez aurkitzea, izena ez delako ondo tekleatu edo beste katalogo batean dagoelako).

Horrela, 7.6. programan erroreen tratamendua egin nahi bada, badaezpada fitxategien izenak ondo zehaztu diren ziurtatzeko, honela aldatu beharko lirateke azken lerroak:

import sys

def erantsi_fitxat (fitx):
	for sarr in fitx.read():
		sys.stdout.writelines(sarr)

for arg in sys.argv[1:]:
	try:
		f = open(arg,'r')
		erantsi_fitxat (f)
	except OSError:
		print('Sistemaren errorea (open)', arg)
	except IOError:
		print('S/Iko errorea', arg)

Probatu programa hori parametro gisa existitzen ez den fitxategi bat pasatuz.

7.2.2.2 Erroreak karaktereen kudeaketarekin. Erabili UTF-8
[aldatu]

Arazorik 'ñ' letrekin? Edo gaztelaniazko azentuekin?

Landu behar dituen testu-fitxategi guztiak UTF-8 kodekeran jartzea komeni zaio informatikariari. Etorkizuneko horrelako hainbat arazo ekidingo du hasiera-hasieratik.

Linux sistema eragileko iconv komandoa guztiz lagungarria da horretan. Fitxategi berri bat jasotzen duen bakoitzean, informatikariak fitxategiaren kodetze-modua zein den jakin beharko du, eta UTF-8 ez bada, momentuan sortu beharko du fitxategiaren UTF-8 bertsioa (iconv komandoa erabiliz, esaterako).

ASCIIrekin bateragarria izateko diseinatu zen. Zenbaki baxuenak dituzten kode-balioak (kode-puntuak) maizago gertatzen diren karaktereak errepresentatzeko erabiltzen dira; horrela byte gutxiagorekin kodetzen dira. Unicodeko lehen 128 karaktereak ASCIIkoak dira, ASCIIko balio bitar bera dute eta horiexek dira byte bakarra erabiltzen dutenak.

Askotan ASCII edo ISO-8859-1 kodekera duen testu fitxategiekin ibiltzen gara. ASCII karakterez osatu eta kodetutako testu bat UTF-8-z ondo kodetutako testua ere bada. Baina testuan agertzen bada ASCII multzoan ez dagoen karaktererik, bat baino ez bada ere, esate baterako 'ñ' letra bat edo 'ü' letra bat, orduan arazoak sortuko dira fitxategi horren erabileran, fitxategi osoa UTF-8rekin kodetu ez bada.

Adibidez, sor ditzagun 'ñ' batzuk dituen testukk.txt izeneko testu fitxategi bat ISO-8859-1 estandarrekin kodetuta. orain dela hamar urte hura zen oso erabilia zen estandar hori. Geroago fitxategi hori utf-8 moduan ireki eta inprimatu nahi badugu horretako karaktereak idatzi nahi baditugu, errore bat aurkituko dugu:

testu1 = ['Begoñako Iñaki Larrañaga']
with open(sst_home + 'testukk.txt', 'w', encoding='ISO-8859-1') as f:
    for lerroa in testu1:
        f.write(lerroa)
        f.write('\n')

# ISO-8859-1 esandarrarekin sortutako fitxategia ireki UTF-8 gisa eta inprimatu bere lerroak:
with open(sst_home + 'testukk.txt', encoding='utf-8') as fitx:
  lerroak = fitx.read().splitlines()
  for lerro in lerroak:
    print(lerro)

# Errore batekin moztuko da exekuzioa testuan ASCII multzoko ez den karaktere bat dagoelako (gutxienez 'ñ' bat)

Baina ez da horrelako errorerik gertatuko 'ñ' karaktererik ez badago:

testu1 = ['Begoniako Inaki Larraniaga']
with open(sst_home + 'testukk.txt', 'w', encoding='ISO-8859-1') as f:
    for lerroa in testu1:
        f.write(lerroa)
        f.write('\n')

with open(sst_home + 'testukk.txt', encoding='utf-8') as fitx:
  lerroak = fitx.read().splitlines()
  for lerro in lerroak:
    print(lerro)

Noski, ez da errorerik sortuko fitxategiaren kodeketaren zabaltzen badugu.

testu1 = ['Begoñako Iñaki Larrañaga']
with open(sst_home + 'testukk.txt', 'w', encoding='ISO-8859-1') as f:
    for lerroa in testu1:
        f.write(lerroa)
        f.write('\n')

with open(sst_home + 'testukk.txt', encoding='ISO-8859-1') as fitx:
  lerroak = fitx.read().splitlines()
  for lerro in lerroak:
    print(lerro)

with open(sst_home + 'testukk_utf8.txt', 'w', encoding='utf-8') as f:
    for lerroa in lerroak:
        f.write(lerroa)
        f.write('\n')

with open(sst_home + 'testukk_utf8.txt', encoding='utf-8') as fitx:
  lerroak = fitx.read().splitlines()
  for lerro in lerroak:
    print(lerro)

Baina hasieran esan dugun bezala, hainbat fitxategi erabili behar badugu, hoberena da hasiera-hasieratik fitxategi guztiak UTF-8 moduan kodetuta edukitzea.

Fitxategi baten karaktere-kodeketa aldatzeko programa bat ikusi dugu atal honetan, baina hori programa horrekin egin daiteke edo zuzenean Linuxeko iconv komandoarekin. Ikusi komandoaren erabilera hemen: https://linux.die.net/man/1/iconv

Gure kasuan, programa bidez egin duguna, honela lortu dezakegu komando bidez ere:

$ iconv -f ISO-8859-1 -t UTF-8  -o testukk_utf8.txt  testukk.txt

7.2.3. Zuzeneko atzipena

[aldatu]

Adibideetan ikusi dugunez, oinarrizko sarrera/irteerako metodoek (read, write, readline, writeline...) fitxategiko datuen atzipen sekuentziala bideratzen dute, eta horretarako fitxategia irekitzean hartzen duen uneko posizioa erabili eta eguneratzen dute (0 posizioa gehienetan), "a" moduaren kasuan (open funtzioan) izan ezik, non fitxategiaren luzeraren balioa (bukaerako posizioa) hartuko baitu uneko posizio gisa, eransketak egin ahal izateko. Zuzeneko atzipena burutzeko aipatutako funtzioak seek metodoarekin konbinatu beharko dira S/Iko beste metodoak (tell metodoarekin ere konbinatuta kasu batzuetan). seek metodoak posizio finko edo erlatibo batean kokatzeko ahalmena eskaintzen du, posizioa eta jatorria zehaztu beharreko parametroak izanik.

seek(pos, jatorri)

Hiru modu edo jatorri bereizten dira, bakoitzak posizioa/desplazamendua aplikatzeko puntu desberdina aukeratzen duela, 0 fitxategiaren hasiera aukeratzen du (modu lehenetsia denez, nahi izanez gero, ez da zehaztu behar), 1 uneko posizioa eta 2 fitxategiaren bukaera.

tell metodoarekin, berriz, uneko posizioa ezagut daiteke, emaitza gisa itzultzen baitu. Hori interesgarria izaten da zuzeneko atzipena atzipen sekuentzialarekin konbinatu nahi denean, posizioarekiko atzipen erlatiboak egiteko adibidez, nahiz eta seek metodoaren 1 jatorriarekin horixe ere egin daitekeen.

7.8. programan zuzen_atzi funtzioa definitzen da, zeinak, parametro baten arabera, posizio jakin batean dagoen luzera finkoko eremu bat irakurri edo idazten duen.

7.8. programa. Zuzeneko atzipenaren erabilera:

import sys

def zuzen_atzi(fitx, pos, buffer, eragik):
	try:
		fitx.seek(pos,0)
	except IOError:
		print("seek-a ez da ondo joan")
		exit
	try:
		if(eragik=="R"):
			return(fitx.read(1))
		else:
			fitx.write(buffer)
	except IOError:
		print("zuzeneko atzipena ez da ondo joan")
		exit

try:
	buf = ""
	fitxat = sys.argv[1]
	f = open(fitxat,'r+')
	buf = zuzen_atzi(f, 2, buf, "R")
	print(buf)
	zuzen_atzi(f, 8, buf, "W")
	f.seek(0)
	print(f.read())
except OSError:
	print("Sistemaren errorea (open)", fitxat)
except IOError:
	print("S/Iko errorea", fitxat)

Programa horretan zuzen_atzi funtzioa definitzen da, fitxategi batean kokatu, pos posizioan, eta idatzi edo irakurri (karaktere bat) egiten da eragik parametroaren arabera. Erroreen tratamendua ere egiten da: programa nagusian funtzioa erabiltzen da 2 posizioan dagoen karakterea (3.a) karakterea irakurtzeko eta 8 posizioan kopiatzeko. Bukaeran fitxategia irakurri (hasieran kokatu eta gero) eta inprimatzen du.

Adibidez, fitxategiaren edukia "abcdefghijkl" bada, emaitza hauxe izango da: "abcdefghcjkl", 2 posizioko 'c' karakterea 8 posizioan idatzi baita, zegoen 'i' karakterearen ordez. Proba ezazu programa fitxategi labur batez (proba_seek fitxategia dago programekin batera) eta posizioak aldatuz programan.

7.2.4. Katalogoen maneiua

[aldatu]

Fitxategiak katalogoetan antolatzen dira eta batzuetan beharrezkoa da katalogoen maneiua egitea programatik.

Adibidez, 7.6. programaren kateatzea katalogo bateko fitxategi guztiekin egin nahi bada, eta katalogoa parametro gisa pasatzen bazaio, programa nagusiaren kodea honela geratuko litzateke: horretarako hainbat funtzio eta metodo interesgarri daude.

import sys

def erantsi_fitxat (fitx):
	for sarr in fitx.read():
		sys.stdout.writelines(sarr)

from os import listdir
from os.path import isfile, join
for izenf in listdir(sys.argv[1]):
	print("FITX:", sys.argv[1], izenf)
	if isfile(izenf):
		f = open(izenf,'r')
		erantsi_fitxat(f)

Ikusten denez, listdir eta isfile metodoak inportatzen dira os eta os.path moduluetatik. Lehenengoak egiten du nahi genuena, baina azpikatalogoak eta bestelako fitxategi motak (socketak, pipeak...) egon daitezkeenez, isfile funtzioa erabiltzen da datu-fitxategiak hautatzeko (kontuz probatzean fitxategi bitarrekin).

Metodo asko dago modulu horietan, horietako batzuk 7.3. taulan islatu dira. Dena den, lagungarria izan daiteke jakitea modulu horietan komando eta sistema-dei ia guztiei dagozkien metodoak daudela.

7.3. taula. Katalogoekin lan egiteko hainbat funtzio eta metHELBURUAodo:
PROTOTIPOA HELBURUA
os MODULUA
listdir(path='.') Katalogoaren osagaiak (parametrorik gabe uneko katalogokoak)
getcwd() Uneko katalogoa
lchmod(path, modua) Baimenak aldatzea modua-rekin
remove(path, *, dir_fd=None) Fitxategiak ezabatzea
os.path MODULUA
abspath(path) Fitxategi edo katalogo baten bide absolutua itzultzen du
isfile(path) Datu-fitxategia den ala ez
isdir(path) Katalogoa den ala ez
getsize(path) Dagokion tamaina
getmtime(path) Azkenez aldatu zeneko denbora

Informazio gehiagorako kontsultatu https://docs.python.org/3/library/os.html eta https://docs.python.org/3/library/filesys.html.

7.2.5. Bestelakoak

[aldatu]

Proiektu handietan fitxategiez gain datu-baseak ere kudeatzen dira. Horrelakoetan datu-baseen hornitzaileek eskaintzen dituzten moduluak, dagozkien metodoekin, erabili beharko dira. Adibidez, MySQL datu-baseak erabiltzeko MySQLdb modulua dago eta hainbat metodo (connect, execute...). Informazioa zabaltzeko 8.5. atalera jo dezakezu.

7.3. INTERNET

[aldatu]

Interneteko konexioak eta Webeko edukiak modu errazean kudeatzea da Pythonen ezaugarri garrantzitsuenetako bat. Horretan sakontzeko liburuan kapitulu oso bat dagoen arren, oinarrizkoena aurreratuko dugu hemen, lehenbailehen ariketa interesgarriak egin ahal izateko. Ohi bezala adibide batekin hasiko gara, 7.9. programa. Bertan urllib.request moduluaren urlopen metodoa erabiltzen da web orri bat (parametro gisa eman behar da URLa) irakurtzeko.

7.9. programa. Web orri baten irakurketa:

#!/usr/bin/python3

import sys
from urllib.request import urlopen
weborri = urlopen(sys.argv[1])
for lerro in weborri:
	lerro = lerro.decode('utf-8')  # kodeketa-arazoengatik
	print(lerro)

Probatzeko testu asko eta HTML kode gutxi duen gune bat zehaztea komeni da, adibidez https://www.berria.eus.

Klase eta metodo asko eta asko daude Interneten aritzeko, baina Webeko edukiak modu errazean erabiltzeko duen ahalmena frogatzeko bigarren adibide bat azalduko dugu: smtplib modulua mezu bat bidaltzeko. SMTP, sendmail eta quit metodoak erabiltzen dira 7.10. programan. Programa martxan jarri ahal izateko posta-zerbitzari bat eta bezero bat behar dira lokalean (Linuxen postfix eta mail instalatzea gomendatzen da). Ohiko posta-zerbitzariekin konektatzea konplexuagoa da (kontuak, baimenak eta konfigurazioa direla-eta).

7.10. programa. Mezu bat bidaltzea:

import smtplib
zerb = smtplib.SMTP('localhost')
mezu = """
	To: ixa@localhost
	From: ixa@localhost
	Subject: Proba
	Kaixo. """
zerb.sendmail('ixa@localhost', 'ixa@localhost', mezu)
zerb.quit()

7.4. ADIBIDEAK

[aldatu]

7.4.1. Enuntziatua: Hitzen maiztasuna

[aldatu]

Fitxategi edo web orri baten gainean hitzen maiztasuna kalkulatzea. 10 aldiz edo gehiago agertzen diren hitzak inprimatuko dira. Bi parametro pasatzen dira: aukera ("fitx"/"URL") eta izena (fitxategiarena edo URL osoa). Hiztegi bat erabiltzen da maiztasunak metatzeko eta bertan gakoak hitzak izango dira, eta lotutako balioa agerpen kopurua. 7.11. programan dago kodea. Gogoratu aurreko adibideetan hainbat kode-zati berrerabiltzen direla.

7.11. programa. Fitxategi edo web orri baten gainean hitzen maiztasuna kalkulatzea:

# Bi parametro: aukera ("fitx"/"URL") eta izena(fitxategiarena edo URL osoa)
import re
import sys
from urllib.request import urlopen

#hitzen taula batetik (hak) maiztasunak eguneratu m hiztegian
def maizt_inkre(hak,m):
	for h in hak:
		if(h in maiz):
			maiz[h] += 1	# inkrem
		else:
			maiz[h] = 1	# 1 balioa

#
aukera = sys.argv[1]
iz = sys.argv[2]
maiz = dict()

if(aukera=="URL"):
	weborri = urlopen(iz)
	for lerro in weborri:
		lerro = lerro.decode('utf-8')
		hitzak = re.findall(r"\w+", lerro)
		maizt_inkre(hitzak,maiz)
else:
	f = open(iz,'r')
	for lerro in f.readlines():
		hitzak = re.findall(r"\w+", lerro)
		maizt_inkre(hitzak,maiz)

# inprimatu 10 aldiz edo gehiago daudenak
for j in maiz:
	if(maiz[j]>10):
		print(j, maiz[j])

7.4.2. Enuntziatua: Zuhaitz bitarra idatzi

[aldatu]

7.12. programan zuhaitz bitar bat definitzeko erabiltzen den egitura eta metodoak azaltzen dira. Funtzioak arbola ezkerretik eskuinera idazten du, algoritmo errekurtsiboa erabiliz.

7.12. programa. Egitura errekurtsibo baten adibidea:

class ZuhBitar():

# zuhaitza erro-adabegiarem (nodoaren) bidez ezagutzen da
    def __init__(self,id):
      self.ezk = None
      self.esk = None
      self.id = id

#gehikuntzak goian. Behean egiteko egitura errepikakorra beharko da
    def gehitu_esk(self,adabegi):
        if self.esk == None:
            self.esk = ZuhBitar(adabegi)
        else:
            zuh = ZuhBitar(adabegi)
            zuh.esk = self.esk
            self.esk = zuh
    def gehitu_ezk(self,adabegi):
        if self.ezk == None:
            self.ezk = ZuhBitar(adabegi)
        else:
            zuh = ZuhBitar(adabegi)
            self.ezk = zuh
            zuh.ezk = self.ezk

# inprimaketa errekurtsiboa ezkerretik eskuinera
    def print_zuh2(self):
        if self.ezk != None:
            self.ezk.print_zuh2()
        print(self.id)
        if self.esk != None:
            self.esk.print_zuh2()

# test

def ProbaZuh():
    Zuh = ZuhBitar("Ane")
    Zuh.gehitu_ezk("Jon")
    Zuh.gehitu_esk("Irati")
    Zuh.gehitu_esk("Garazi")
    Zuh.print_zuh2()

ProbaZuh()

7.5. PROPOSATUTAKO ARIKETAK

[aldatu]
  1. more programaren egitekoa burutzen duen programa egin behar duzu. Testu-fitxategi bat parametro gisa jasota, pantailaz pantaila idazten joango dira lerroak. Pantaila osatu eta gero, teklatutik irakurri, eta, 'q' bada, amaitu egingo da, bestela, beste edozein karaktere jasota, hurrengo pantaila idaztera pasako da. Sinplifikatzearren, pantaila baten edukia 40 lerrotan ezarriko da. Bigarren bertsio batean gehitu erroreen tratamendua.
  2. bilatu_eta_ordezkatu izeneko programa bat egin behar duzu, zeinek fitxategi baten gainean karaktere-kate bat bilatu eta beste batez ordezkatuko duen. Hiru parametro emango zaizkio programari, beraz, fitxategiaren izena, bilatzeko katea eta ordezkatzekoa. Bigarren bertsio bat egin, kate bat bilatu beharrean espresio erregular bat bilatuko duena.
  3. 7.9. programa osatu web orrian beltzez (dagokion HTML etiketa bilatu beharko da) idatzitako zatiak inprimatzeko.
  4. Hitzen maiztasunak kalkulatzeko 7.11. programa ondo dago, baina hainbat hobekuntza egin nahi ditugu:
    1. Maiztasunak kalkulatzeko hiztegia klase moduan definitu behar da.
    2. Erroreen tratamendua egin behar da: parametro desegokiak, fitxategia ez egotea, URL-a ez aurkitzea...
    3. Maiztasunak ematean ordena garrantzitsua da, handienetik txikienera.
Aldaketak egin, hori guztia lortzeko.
5. Aldatu aurreko programa, hitzen ez baizik eta n-gramen maiztasuna kalkula dezan. Parametro moduan pasako da n zenbakia. n-gramak n karakterezko multzo teilakatuak dira; adibidez "Python lengoaia" katean 3-gramak hauek dira: " Py", "Pyt", "yth", "tho", "hon", "on ", "n l", " le"...