Osa 6

Skriva filer

Nu har vi sett hur man kan läsa data från filer, men det är naturligtvis också möjligt att skriva data till filer. I en vanlig situation behandlar programmet någon data och skriver det i en fil, så att det kan senare användas eller behandlas vidare av något annat program.

Vi kan skapa en ny fil varje gång vi vill skriva data, men vi kan också lägga till data i en fil som redan finns. I båda fallen använder vi open-funktionen som vi bekantade oss med i den förra delen. För att skriva filer måste vi ge funktionen ett andra argument.

Skapa en fil

Om du vill skapa en ny fil ska du anropa funktionen open med w som andra argument. Det här indikerar att filen ska öppnas i skrivläge. Funktionsanropet skulle då kunna se ut så här:

with open("ny_fil.txt", "w") as fil:
    # vi skriver till filen här

Obs! Om filen redan finns, kommer allt innehåll att skrivas över. Man ska vara väldigt försiktig när man skapar nya filer.

När filen är öppen, kan du skriva data i den. Du kan använda metoden write, som tar strängen som ska skrivas som sitt argument:

with open("ny_fil.txt", "w") as fil:
    fil.write("Hej alla!")

När du kör programmet, dyker en ny fil med namnet ny_fil.txt upp i mappen. Innehållet borde se ut så här:

Exempeldata

Hej alla!

Om du vill ha radbyten i filen, måste du lägga till dem för hand. Funktionen write fungerar inte som print-funktionen, även om de har likheter. Följande program…

with open("ny_fil.txt", "w") as fil:
    fil.write("Hej alla!")
    fil.write("Andra raden")
    fil.write("Sista raden")

…skulle resultera i en fil som denna:

Exempeldata

Hej alla!Andra radenSista raden

Radbrytningar får man till stånd med att inkludera \n i strängarna som ges som argument till write-funktionen:

with open("ny_fil.txt", "w") as fil:
    fil.write("Hej alla!\n")
    fil.write("Andra raden\n")
    fil.write("Sista raden\n")

Nu borde innehållet i ny_fil.txt se ut så här:

Exempeldata

Hej alla! Andra raden Sista raden

Loading

Lägga till data i en befintlig fil

Om du vill lägga till data i slutet av en fil istället för att skriva över en hel fil, kan du använda argumentet a istället för w.

Om filen inte ännu finns, fungerar det här läget på samma sätt som skrivläget.

Följande program öppnar filen ny_fil.txt och lägger till några rader text i slutet:

with open("ny_fil.txt", "a") as fil:
    fil.write("Rad fyra\n")
    fil.write("Ännu en till rad\n")

När programmet körs, borde innehållet i filen se ut på följande sätt:

Exempelutskrift

Hej alla! Andra raden Sista raden Rad fyra Ännu en till rad

I praktiken är det inte så vanligt att man lägger till innehåll i en befintlig fil.

Oftare läser man en fil, behandlar man data och till sist skrivs filen över med nya data. Till exempel om man vill ändra på innehållet i mitten av en fil, är det vanligtvis enklast att skriva över hela filen.

Loading

Skriva CSV-filer

CSV-filer kan skrivas rad för rad med write-metoden, precis som med vilken som helst annan fil. Det följande exemplet skapar filen programmerare.csv som innehåller namnet, programmeringsmiljön, favoritprogrammeringsspråket och antalet år arbetserfarenhet hos en programmerare. Fälten skiljs åt med semikolon.

with open("programmerare.csv", "w") as fil:
    fil.write("Erik;Windows;Pascal;10\n")
    fil.write("Mats;Linux;PHP;2\n")
    fil.write("Anton;Linux;Java;17\n")
    fil.write("Emilia;Mac;Cobol;9\n")

När programmet körs får vi följande fil:

Exempelutskrift

Erik;Windows;Pascal;10 Mats;Linux;PHP;2 Anton;Linux;Java;17 Emilia;Mac;Cobol;9

Hur är det om data som ska skrivas finns i en lista i datorns minne?

programmerare = []
programmerare.append(["Erik", "Windows", "Pascal", 10])
programmerare.append(["Mats", "Linux", "PHP", 2])
programmerare.append(["Anton", "Linux", "Java", 17])
programmerare.append(["Emilia", "Mac", "Cobol", 9])

Vi kan konstruera den sträng som vi vill skriva som en f-sträng, och skriva den klara raden i filen:

with open("programmerare.csv", "w") as fil:
    for person in programmerare:
        rad = f"{person[0]};{person[1]};{person[2]};{person[3]}"
        fil.write(rad+"\n")

Om varje lista skulle vara väldigt lång, skulle det vara arbetsdrygt att konstruera strängen för hand och då skulle vi istället kunna använda en for-loop:

with open("programmerare.csv", "w") as fil:
    for person in programmerare:
        rad = ""
        for varde in person:
            rad += f"{varde};"
        rad = rad[:-1]
        fil.write(rad+"\n")

Tömma innehållet i en fil och ta bort en fil

Ibland behöver vi tömma innehållet i en fil. Då kan vi helt enkelt öppna filen i skrivläge och därefter stänga filen:

with open("fil_som_ska_tommas.txt", "w") as fil:
    pass

Observera att with-blocket nu bara innehåller instruktionen pass, som inte gör något. Python tillåter inte tomma block, så därför använder vi den här instruktionen här.

Det är också möjligt att undvika with-blocket och istället använda följande instruktion:

open('fil_som_ska_tommas.txt', 'w').close()
Loading
Loading

Behandla data i CSV-format

Låt oss skapa ett program som utvärderar elevernas framgång under en kurs. Programmet läser en CSV-fil som innehåller de veckovisa poängen som den studerande fått under kursens lopp. Programmet räknar ihop poängen och utvärderar därefter vilket vitsord de räcker till. Till slut skapar programmet en CSV-fil som innehåller poängsumman och vitsordet för varje elev.

CSV-filen som vi har tillgång till när vi börjar ser ut så här:

Exempeldata

Pärla;4;2;3;5;4;0;0 Paula;7;2;8;3;5;4;5 Pirjo;3;4;3;5;3;4;4 Emilia;6;6;5;5;0;4;8

Programmets logik är uppdelad i tre funktioner: läsande av filen och behandlande av innehållet, vitsordsberäkning och skrivande av en ny fil.

Filens inläsning sker enligt det vi lärt oss i den förra delen. Data lagras i ett lexikon där nyckeln är elevens namn och värdet är en lista på poängen som eleven i fråga har fått, i heltalsform:

def las_veckopoang(filnamn):
    veckopoang = {}
    with open(filnamn) as fil:
        for rad in fil:
            delar = rad.split(";")
            lista = []
            for poang in delar[1:]:
                lista.append(int(poang))
            veckopoang[delar[0]] = lista

    return veckopoang

Den andra funktionen beräknar vilket vitsord ett visst antal poäng räcker till. Funktionen används av den tredje funktionen, som skriver resultaten i en fil:

def vitsord(poang):
    if poang < 20:
        return 0
    elif poang < 25:
        return 1
    elif poang < 30:
        return 2
    elif poang < 35:
        return 3
    elif poang < 40:
        return 4
    else:
        return 5

def spara_resultat(filnamn, veckopoang):
    with open(filnamn, "w") as fil:
        for namn, lista in veckopoang.items():
            summa = sum(lista)
            fil.write(f"{namn};{summa};{vitsord(summa)}\n")

Strukturen tillåter oss skapa en mycket enkel huvudfunktion. Observera att filnamnen ges som argument i huvudfunktionen:

veckopoang = las_veckopoang("veckopoang.csv")
spara_resultat("resultat.csv", veckopoang)

När huvudfunktionen körs, skapas filen resultat.csv med följande innehåll:

Exempeldata

Pärla;18;0 Paula;34;3 Pirjo;26;2 Emilia;41;5

Notera att alla funktioner ovan är relativt enkla till sin funktionalitet – de har en uppgift var. Det här är ett vanligt och rekommenderat sätt att skapa större helheter när man programmerar. När en funktion har en uppgift är det enklare att säkerställa att den fungerar på önskat sätt. Det här gör det också enklare att senare ändra på programmet och lägga till ny funktionalitet.

Om vi till exempel vill ha en funktion för att skriva ut vitsordet för enskild studerande, kan vi skapa en ny funktion som använder sig av en befintlig funktion i koden:

def hamta_vitsord(person, veckopoang):
    for namn, lista in veckopoang.items():
        if namn == person:
            return vitsord(sum(lista))


veckopoang = las_veckopoang("veckopoang.csv")
print(hamta_vitsord("Paula", veckopoang))
Exempeldata

3

Om vi märker att någon funktionalitet i programmet kräver åtgärdande, kommer ändringar inte att orsaka följder överallt i koden. Om vi till exempel vill ändra på vitsordsgränserna, behöver vi bara ändra på funktionen som räknar ut vitsordet – alla andra funktioner som använder den här funktionen skulle fortfarande fungera, med de nya gränserna. Om koden för den här funktionaliteten skulle vara splittrad, finns det en risk att vi glömmer att uppdatera koden på något ställe. Det här skulle antagligen orsaka problem.

Loading
Loading
Loading
Loading...
:
Loading...

Log in to view the quiz

Du har nått slutet av den här delen! Fortsätt till nästa del:

Se dina poäng genom att klicka på cirkeln nere till höger av sidan.