PYTHON liburua/Sistemaren gaineko aukerak
9. Sistemaren gaineko aukerak
[aldatu]Lau azpiataletan banatuko ditugu Pythonetik balia daitezkeen aukerak: sistemaren komandoak, administrazioa, sistema-deiak eta multithreading bidezko konkurrentzia.
Lehen bi ataletako kontzeptuak lantzeko on-line dagoen liburu hau gomendatzen dugu: Linux: Sistemaren eta sarearen administrazioa (http://ueu.org/download/liburua/LINUXDebian.osoa.pdf). Sistema-deien inguruan dokumentu hau kontsulta daiteke: http://www.sc.ehu.es/acwlaalm/seo/teoria/2-gaia.pdf.
Zazpigarren kapituluan aipatu den os moduluak aukera handiak eskaintzen ditu sistema eragilearekiko interakziorako. Nagusiki bi dira SEak eskaintzen dituen eragiketak: komandoak eta sistema-deiak. Komandoak programa exekutagarriak izan ohi dira eta sistema-deien bidez programatu ohi dira. Sistema-deiak, berriz, SEaren oinarrizko funtzioak dira eta sistemen rogramazioaren oinarria. Informazio gehigarria URL honetan aurki daiteke: https://docs.python.org/3/library/os.html.
Kontuan hartu behar da Unix/Linux sistemetan bakarrik direla erabilgarriak ondoren azalduko ditugun metodoak.
Beste kapituluetan aukera eman dugu exekuzioak hodeian egiteko Colab bitartean edo norberaren konputagailuan. Kapitulu honetan ordea, norberarenean bakarrik egin ahal izango da, norberaren sstema eragilean.
9.1. SISTEMAREN KOMANDOAK
[aldatu]Komandoak exekutatzeko biderik erosoena os.system metodoa erabiltzea da. Parametro gisa komando-lerroa adierazten duen karaktere-katea izango da.
Adibidez 9.1. programan honako hau egiten da: proba1 fitxategia bertan sortu ('1' karakterea izango da haren edukia), berri izeneko katalogo berri bat sortu, bertara aurreko fitxategia kopiatu (laneko izenarekin) eta hasierako fitxategia (proba1) ezabatu.
9.1. programa. Komandoen erabilera Pythonetik:
import os
os.system("echo '1' >proba1")
os.system("mkdir berri")
os.system("cp proba1 berri/laneko")
os.system("rm proba1")
Modu orokor horrez gain, komando espezifikoak adierazteko metodoak ere eskaintzen ditu modulu honek. Arazotxo bat dute metodo hauek, haien izena batzuetan komando berarena da (chown, chroot, chmod, mkdir, mkfifo...), baina beste batzuetan beste luzeago bat (link eta ez ln, remove eta ez rm, rename eta ez mv...).
9.2. programa. Komandoei dagozkien metodo espezifikoak:
import os
os.system("echo '1' >proba1")
os.mkdir("berri")
os.system("cp proba1 berri/laneko")
os.remove("proba1")
9.2. programa aurrekoaren baliokidea da, baina kasu honetan mkdir eta remove metodo espezifikoak erabili dira system metodo orokorraren ordez.
9.3. programan, berriz, sistemaren kontrolerako komando batzuen erabilera ikus daiteke. top erabiltzen da prozesadorearen egoeraz jabetzeko, vmstat memoriarako, df disko-partizioetarako eta ifconfig sare-interfazeetarako.
import os
print("CPU:")
os.system("top -b -n 1 | head -2")
print("\nMemoria:")
os.system("vmstat")
print("\nPartizioak:")
os.system("df")
print("\nSare-interfazeak:")
os.system("/sbin/ifconfig")
Komandoen exekuzioak itzultzen duena errore-kodea izan ohi da, baina eragina normalean irteera estandarrean islatzen da (edo, adibideetan egin den bezala, fitxategiren batean irteera estandarra birbideratuz). Irteera hori aldagairen batean eskuratzeko subprocess moduluaren check_output metodoa erabil daiteke. Adibidez:
emaitza = subprocess.check_output('df')
Bestalde, komandoen erabilera errazteko, eta batez ere sistemaren eraginkortasunaren kontrola errazteko, psutil modulua erabil daiteke (https://github.com/giampaolo/psutil). Bertako metodoen bidez sistemaren baliabideak (CPU, memoria, diskoa, sarea...) nola erabiltzen ari diren monitoriza daiteke. Aurretik instalatu behar da komando honen bidez:
sudo apt-get install python-psutil
9.4. adibidean erabileraren adibide bat agertzen da.
9.4. programa. Komandoei dagozkien metodo espezifikoak:
import psutil
print("CPU:\n", psutil.cpu_times())
print("\nMemoria:\n", psutil.virtual_memory())
print("\nPartizioak:\n", psutil.disk_partitions())
print("\nSare-interfazeak:\n", psutil.net_if_addrs())
9.2. ADMINISTRAZIOA
[aldatu]Administrazio-lanak burutzeko komandoak eta konfigurazioa-fitxategiak erabiltzen dira. Komando-fitxategiak osatu ohi dira lanak automatizatzeko scripting delakoaren bidez. Komando-fitxategi horietan komandoak eta script-lengoaiak konbinatu ohi dira eta Python, gero eta gehiago, erabiltzen da script-lengoaia gisa. Adibide batzuen bitartez landuko ditugu (URL honetan informazio gehiago horretaz: https://www.linuxjournal.com/content/python-scripts-replacement-bash-utility-scripts.
Hasteko adibide bat: testeatzeko script bat (wifi konexioarekin bakarrik proba daiteke). Linuxen sudo iw wlan0 scan komandoaren bidez inguruan dauden sareen informazioa jaso daiteke (baimena behar da; hori dela-eta pasahitza eskatuko digu sistemak). Ariketa honetarako lerro desberdinetan dauden eremu hauek interesatzen zaizkigu: identifikazioa (SSID) eta seinalearen kalitatea (signal). 9.5. programan inguruko wifi konexioen datu horiek selekzionatzen ditugu.
9.5. programa. Inguruko wifien informazio laburtua:
import os
os.system("sudo iw wlan0 scan >tmp")
for lerro in open('tmp','r').readlines(): # lerroka
if "signal" in lerro:
ahal = lerro
if "SSID" in lerro:
print(lerro, ahal)
os.system("rm tmp")
Gauza konplexuagoak egin daitezke, adibidez konexioa aktibatzea. Ikus adib. <http://stackoverflow.com/questions/20470626/python-script-for-raspberrypi-to-connect-wifi-automatically>.
Bigarren adibidean sistemaren erabileraz arituko gara. ps -aux komandoaren bidez lortzen den informazioa multzokatzen da erabiltzaileen arabera 9.6. adibidean, erabiltzaile bakoitzeko CPUren portzentaje metatuak lortuz.
Hona hemen komandoaren lehen lerroen adibide bat:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 33736 3044 ? Ss 16:59 0:01 /sbin/init
root 2 0.0 0.0 0 0 ? s 16:59 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? S 16:59 0:00 [ksoftirqd/0]
root 5 0.0 0.0 0 0 ? S< 16:59 0:00 [kworker/0:0H]
root 7 0.0 0.0 0 0 ? S 16:59 0:01 [rcu_sched
Lehen eta hirugarren zutabeak dira interesatzen zaizkigunak. Lehena erabiltzailea denez, hiztegia indexatzeko erabil dezakegu. Hiztegi batean CPUren balioak metatuko ditugu (lagungarria izango da 6. kapituluan landutako hiztegiak).
9.6. programa. CPUren erabilera erabiltzaileen arabera:
import os
cpu = dict()
os.system("ps -aux >tmp")
for lerro in open('tmp','r').readlines(): # lerroka
hitzak = lerro.split()
if hitzak[0]!='USER': # lehen lerroa ez
if hitzak[0] in cpu: # hiztegian?
cpu[hitzak[0]] += float(hitzak[2])
else:
cpu[hitzak[0]] = float(hitzak[2])
for erab in cpu: # erabiltzaileka
print(erab,cpu[erab])
Beste aukera bat dago, Python programatik komandoen erreferentzia kendu eta komando-lerro hau idatzi:
ps -aux | python3 p9-6_script2b.py
Gainera, programaren sarrerak ez du tmp izan behar, sarrera estandarra baizik. Hori dela-eta, irakurketa errazten da, honela geratuz:
for lerro in sys.stdin:
Konplexutasuna igoz, 9.7. adibidean, azkenik, http://askubuntu.com/questions/547437/find-delete-duplicated-files-on-multiple-harddisks-at-once web orrian aurkitutako scriptaren moldaketa agertzen da. Bertan, parametro gisa jasotzen diren katalogoetan bilatzen dira izen bereko fitxategiak, eta izen errepikatuak pantailaratzen dira.
Horretarako erabilgarri gertatzen da os.walk metodoa, zeinaren bidez katalogo baten azpian dauden azpikatalogo bakoitzeko (bera barne) azpikatalogo eta fitxategi guztiak itzultzen dituen. Horrela hirukoteen zerrenda bat itzultzen du, hirukote bat azpikatalogo bakoitzeko, hirukotearen elementuak hauek izanik: (azpi)katalogoaren bidea, azpian dituen azpikatalogoak (zerrenda) eta azpian dituen fitxategiak (zerrenda).
9.7. programa. Fitxategi bikoiztuak bilatzeko scripta:
#http://askubuntu.com/questions/547437/find-delete-duplicated-files-on-multiple-harddisks-at-once
import os
import sys
izenak = [] # izen sinpleak biltzeko
fitxategiak = [] # izen osoak biltzeko
def bilatu_fitx(dir): # katalogoaren fitx-ak os.walk bidez
l = []; l2 = []
for erro, dir_ak, fitx_ak in os.walk(dir):
for fitx in fitx_ak:
l.append(fitx) # izen sinpleak
l2.append(erro+"/"+fitx) # izen osoak
return (l, l2) # itzuli izen sinpleak eta osoak
for dir_i in sys.argv: # argumentuak
print("Fitxategien zerrenda sortzen...", dir_i)
izenak = izenak+bilatu_fitx(dir_i)[0] # 0-sinpleak
fitxategiak = fitxategiak+bilatu_fitx(dir_i)[1] # 1-osoak
print("Bikoiztuak detektatzen ("+str(len(izenak)),"fitx)...")
for izen in izenak:
n = izenak.count(izen)
if n > 1:
print("-"*60,"\n> bikoiztuta:", izen, n, "\n")
for item in fitxategiak:
if item.endswith("/"+izen): #endswith metodoa bukaerarako
print(item)
Programa probatzeko onena da bi azpikatalogo sortzea (dir1 eta dir2) eta bakoitzean hainbat fitxategi kopiatzea. Deitzean bi katalogoen izenak parametro gisa pasako dira, eta fitxategiren bat bi katalogoetan baldin badago, detektatuko da.
9.3. SISTEMA-DEIAK
[aldatu]Esan bezala sistema-deiak SEaren oinarrizko funtzioak dira. Python sistemen programazioari eta administrazioari begira lengoaia egokia da, beste gauzen artean, sistema-deiak zuzenean erabiltzea bideratzen duelako.
Sistema-deien bidez sistemaren baliabideak zuzenean erabil daitezke. Adibidez:
- prozesuen informazioa eskuratzea eta aldatzea: getpid, getuid, seteuid...
- prozesuak sortzea, exekutatzea, itxoitea eta hiltzea: fork, exec-en aldaerak (execl, execvp...), wait, kill
- komunikazioak: pipe, mkfifo...
- fitxategiak (zuzenean kanal-zenbakiaren bidez): open, read, write, lseek, dup...
Hemen ez dugu tokirik sistema-deien inguruko kontzeptuetan sakontzeko, baina aipatutako gunean horren inguruko informazio ugari aurki daiteke. Oro har, sistema-dei bakoitzari metodo bat dagokio.
9.8. adibidean sistemen programazioan ohikoak diren bi eragiketa (metodoak Pythonez) erabiltzen dira: prozesu umea sortzea (fork) eta komunikazio-kanala sortzea (pipe). Adibidean sortzen den kanalaren bidez umeak idazten duena gurasoak irakurtzen du eta pantailaratzen du.
# FIFO batez komunikatzea
import os, sys, time
# izen gabe FIFOa (pipe) sortzea
ir,id=os.pipe() # bi zenbaki itzultzen du bat irakurtzeko eta bestea idazteko
# 2 fitxategi
blokel=1024
r=os.fdopen(ir,'r',blokel) # irakurketarako ireki
w=os.fdopen(id,'w',blokel) # idazketarako ireki
pid = os.fork()
if pid: # gurasoa (irakurlea)
w.close()
while 1:
data=r.readline() # FIFOtik irakurri
if not data: break
print("gurasoa read: ", data.strip()) # inprimatu pantailan
else: # umea (idazlea)
r.close()
for i in range(10):
w.write("lerroa: " + str(i) + "\n") # FIFOn idatzi
w.flush() # memoriatik S/Ira
time.sleep(1) # segundo bat itxoin
9.4. MULTITHREADING
[aldatu]Multiprozesadoreen aukeraz baliatzeko eta aplikazioak azkartzeko hari anitzeko edo multithreading izeneko mekanismoa erabiltzen da. Hariak (thread) exekuzio-fluxuak dira, prozesuaren memoria eta fitxategiak partekatzen dituztenak, baina prozesadoreari (edo prozesadoreei) begira lehiakideak direnak. Gaur egungo programazio konkurrente eta paraleloaren funtsa dira, eta programazio-lengoaien esku dago haiei etekina ateratzea (beti azpiko sistema eragileak uzten duenean).
Pythonen kasuan alde handi samarra dago ezaugarri honi begira Python2.4 bertsiotik aurrera. Lehenago thread moduluari dagozkion metodoak erabiltzen ziren helburu horrekin. Ahalmen mugatua du modulu honek, adibidez prozesu umeen zain geratzeko. Python2.4 bertsiotik aurrera muga horiek gainditu dira threading moduluaren bidez, eta, gainera, objektuei orientatutako programazioari eman zaio lehentasuna. Hala ere, aurreko moduluaren metodoak ere erabil daitezke, baina Python3 erabiltzen bada, aldaketatxo bat gertatu da: _thread izena zehaztu behar da modulu hori erabiltzeko. Laburbilduz, Python3-n bi modulu erabili ahal izango dira, _thread izenekoa, sinplea baina mugatua; eta threading izenekoa, osatuagoa eta objektuei orientatua.
Programazioari dagokionez, hari bakoitzari funtzio bat edo metodo bat dagokio. Programaren arabera hariek funtzio/metodo bera erabiliko dute (nagusi-morroi eredua deitu ohi denean morroiekin egiten den bezala) edo hari bakoitzak metodo/funtzio berezi bat edukiko du (pipe eredua da horren adibidea). Bi kasuetan funtzioak/metodoak definitu eta gero, programa nagusia harien sorreraz arduratuko da.
Adibide sinple batekin hasiko gara. Bi hari sortuko ditugu eta bakoitzak ordua inprimatuko du hiru aldiz denbora-tarte bat itxaron eta gero. Hori programatzeko bi aukera ditugu: bertsio zaharretan erabiltzen zen thread klaseko start_new_thread metodoa (p-thread-1.py); eta threading klaseko Thread metodoa (p-thread-1b.py).
Lehen kasuan, programa nagusia zain geratzen da etengabe, bestela bukatuko litzateke hariak amaiaraziz. Beraz, probatzean CTRL-C bidez amaiarazi beharko duzu.
9.9a. programa. Bi hari, bakoitzak bere ordua idazten:
mport _thread as thread
import time
# hariari dagokion funtzioa
def inpri_denbora(haria, atzerapena):
kontag = 0
while kontag < 3: # 3 aldiz
time.sleep(atzerapena) # itxoitea (segundotan)
kontag = kontag + 1
print(haria, "- ordua:", time.ctime(time.time()))
# programa nagusia: bi hari sortuko duena
try:
thread.start_new_thread(inpri_denbora,("1. haria",2,))
thread.start_new_thread(inpri_denbora,("2. haria",4,))
except:
print("Errorea: ezin haria sortu")
# itxoitea harien bukaerararte
while 1:
pass
Bigarren kasuan, gomendagarriena, programa nagusian ez da itxaron behar; baina hari bakoitzeko bi urrats egiten dira: hariaren definizioa Thread metodoaren bidez batetik, eta haria martxan jartzea start metodoaz.
9.9b. programa. Bi hari, bakoitzak bere ordua idazten:
from threading import Thread
import time
# hariari dagokion funtzioa
def inpri_denbora(haria, atzerapena):
kontag = 0
while kontag < 3: # 3 aldiz
time.sleep(atzerapena) # itxoitea (segundotan)
kontag = kontag + 1
print(haria, "- ordua:", time.ctime(time.time()))
# programa nagusia: bi hari sortuko duena
try:
t1=Thread(target=inpri_denbora, args=("1. haria",2,))
t1.start()
t2=Thread(target=inpri_denbora, args=("2. haria",4,))
t2.start()
except:
print("Errorea: ezin haria sortu")
threading modulua oso ahaltsua da, baina konplexua ere. Oinarrizko metodoak hauek dira (Thread klasean, baina threading klasetik eskuragarri):
- run(): Hariaren sarrera-puntua definitzeko objektuetan.
- start(): Haria abiaraztea run metodoa erabiliz (objektuetan) edo funtzio batez.
- join([time]): Harien zain geratzea.
- isAlive(): Haria indarrean dagoen ala ez galdetzea.
- getName(): Hariaren izena lortzea.
- setName(): Hariaren izena ezartzea.
Aurreko moduluaren metodoez gain, beste batzuk ditugu eskuragarri threading moduluan:
- threading.activeCount() : Sortutako hari aktiboen kopurua itzultzen du.
- threading.currentThread() : Hari deitzaileari dagozkion harien kopurua itzultzen du.
- threading.enumerate() : Indarrean dauden harien izenak itzultzen ditu, zerrenda batean.
Gainera, klase-herentzia bidez klase berriak defini daitezke, objektuei orientatutako metodologiari jarraituz. Horrela 9.9b. adibidea eratorritako klase batez ebazten da 9.9c. programan. Bertan, DenbHaria klasea definitzen da, threading.Thread klasetik eratorrita, beraz, haren objektuei klasearen metodo guztiak aplika dakizkieke. Gure kasuan run metodoa birdefinitu da eta start metodoa aplikatzen da hura aktibatzeko.
9.9c. programa. Hariak klase eratorri gisa:
import threading
import time
class DenbHaria (threading.Thread):
def __init__(self, threadID, izen, kont):
threading.Thread.__init__(self)
self.threadID = threadID
self.izen = izen
self.kont = kont
def run(self):
inpri_denbora(self.izen, self.kont)
def inpri_denbora(haria, atzerapena):
kontag = 0
while kontag < 3: # 3 aldiz
time.sleep(atzerapena) # itxoitea (segundotan)
kontag = kontag + 1
print(haria, "- ordua:", time.ctime(time.time()))
try:
# Hariak sortzea
t1 = DenbHaria(1, "Thread-1", 2)
t2 = DenbHaria(2, "Thread-2", 4)
# Hariak abiatzea
t1.start()
t2.start()
except:
print("Errorea: ezin haria sortu")
Aurreko programa nahiko sinplea da, baina ez da oso praktikoa. Praktikotasunaren bila, p-koman-2.py adibideko programa harien bidez programatuko dugu (threading modulua erabiliz). Zazpigarren kapituluan egindako baten egokitzapena da. Bertan hainbat URLtatik irakurtzen da, eta horretarako hari bat sortzen da hari bakoitzeko. Irakurritakoa inprimatzen da HTML etiketak kenduta, eta horretarako erabiltzen da instalatu dugun html2text modulua.
9.10. programa. Webguneak irakurtzen hari desberdinetatik:
import sys
import threading
from urllib.request import urlopen
from html2text import html2text
# 7.9 programaren egokitzapena
# hariari dagokion funtzioa
def eskuratu_url(url):
print(url)
orri=urlopen(url)
for lerro in orri:
lerro = lerro.decode('utf-8')
txt = html2text(lerro) # html etiketak kentzeko
if len(txt)>20: # 20 karakatere baino gehiago
print(txt)
urlak = ["http://sustatu.eus", "http://ueu.eus"]
for u in urlak:
t = threading.Thread(target=eskuratu_url, args = (u,))
t.start()
Liburu honetan ez dugu asko sakonduko gai honetan. Adibidez ez gara sartuko sinkronizazio eta komunikaziorako dauden klase eta metodoetan. Edozein kasutan http://www.tutorialspointkk.com/python/python_multithreading.htm helbidean informazioa osa daiteke (https://docs.python.org/3/library/threading.html).
Python3-ko zehaztasunetarako). Adibide konplexuago bat helbide honetan kontsulta daiteke: http://www.toptal.com/python/beginners-guide-to-concurrency-and-parallelism-in-python.
9.5. ADIBIDEAK
[aldatu]9.5.1. 1. enuntziatua: grep paraleloa
[aldatu]Katalogo baten fitxategi guztietan testu baten agerpena bilatzen duen programa egin behar da, baina fitxategi bakoitzean bilaketa hari batez egingo da. Hari bakoitzaren kodea sinplea izango da, grep komandoa erabiltzea baino ez. Komando horrek 0 itzuliko du, karaktere-katea aurkitu badu. Komandoaren irteera pantailatik ager ez dadin, /dev/null dispositibo nulura birbideratuko da. Objektuen orientazioarekin egingo dugu, eta horretarako 9.9c. programan oinarrituko gara.
9.11. programa. grep bidezko bilaketa konkurrentea:
import threading
import os
import sys
class BilaFitxHaria (threading.Thread):
def __init__(self, fitx, st):
threading.Thread.__init__(self)
self.fitx = fitx
self.st = st
def run(self):
bila_fitx(self.fitx, self.st)
def bila_fitx(f, kate):
em = os.system("grep " + kate + " " + f + " >/dev/null")
if not em:
print(f)
try:
for f in os.listdir(sys.argv[1]): # katalogoko fitxategi bakoitzeko
if(os.path.isfile(f)): # fitxategiekin bakarrik
t = BilaFitxHaria(f,sys.argv[2])
t.start()
except:
print("Errorea: ezin haria sortu")
Erabiltzeko bi parametro pasa behar dira: katalogoa eta bilatu nahi den karaktere-katea. Bilaketa katalogoko fitxategietan egiten da azpikatalogoetan sartu gabe. Azpikatalogoetan sakontzeko os.walk metodoa erabil daiteke.
9.5.2. 2. enuntziatua: FIFOak harien bidez
[aldatu]9.8. programan azaldutako FIFOaren adibidea harien bidez ebatzi behar da, prozesuen bidez erabili beharrean. Horretarako, bi funtzio definituko dira: irakurlea bata, idazlea bestea. Thread metodoaren bidez abiatuko dira. Sistema-dei gehienak (prozesuak sortzearenak kenduta) berdin geratzen dira.
9.12a. programa. FIFO batez komunikatzea hariak erabiliz:
# FIFO batez komunikatzea hariak erabiliz
import os, sys, time
import threading
def irakurle(irf):
print("...irakurtzen")
while 1:
data=irf.readline() # FIFOtik irakurri
print("irakurle read: ", data.strip()) # inprimatu pantailan
return
def idazle(idf):
global harikop
print("...idazten")
for i in range(10):
idf.write("lerroa: " + str(i) + "\n") # FIFOn idatzi
idf.flush() # memoriatik S/Ira
time.sleep(1) # segundo bat itxoin
return
# izen gabe FIFOa (pipe) sortzea
ir,id=os.pipe() # bi kanal, bat irakurtzeko eta bestea idazteko
# 2 fitxategi
blokel=1024
ird=os.fdopen(ir,'r',blokel) # irakurketarako ireki
idd=os.fdopen(id,'w',blokel) # idazketarako ireki
print("Hasiera")
t1=threading.Thread(target=irakurle,args=(ird,))
t1.start()
print("irakurlea martxan")
t2=threading.Thread(target=idazle,args=(idd,))
t2.start()
print("idazlea martxan")
9.6. PROPOSATUTAKO ARIKETAK
[aldatu]1) Aldatu 9.6. programa CPUren portzentajeak metatzeaz gain, memoriakoak ere metatzeko. Gainera, emaitzek erabileraren arabera sailkatuta agertu behar dute (sort komandoa erabil daiteke horretarako, baina Pythonen klaseak ere).
2)Aldatu 9.10. programa, honako helburuak lortzeko:
- Irakurri behar diren web orrien helbideak fitxategi batean egotea.
- Hariak klase eratorri gisa definitzea.
- Irakurtzen diren orrietatik testua lortu ondoren, inprimatu beharrean hiztegia osatu eta maiztasunak kalkulatzea. Horretarako hari guztien informazioa jaso beharko da.
3) Egin Python programa bat bi matrizeren arteko biderketa egiteko harien bitartez. Hari bakoitzaren funtzioa izango da errenkada eta zutabe bat biderkatzea eta emaitzaren elementu bat lortzea. Bukaeran emaitza inprimatuko da. Oinarri gisa 6.4. programa har daiteke.