Centralt innehåll
- Skrivning och läsning av lagrad data.
- Det valda programspråkets kontrollstrukturer.
- Skapande av användarvänliga gränssnitt.
Fakta
Filer
I tidigare program har all information om vad användaren gjort med programmet försvunnit så fort programmet är klart. Ofta vill man spara någon information om vad som gjorts och det kan man göra i filer. Det innebär att en fil på datorn används för att lagra information på. Det kan vara information om vad programmet gjort föregående gånger det körts eller så kan det vara en lång lista med information som programmet behöver för att köras.
Mappar eller kataloger (eng. directory) som programmerare ofta kallar det för används för att organisera filer. Kataloger kan innehålla andra kataloger. Strukturen kallas ofta för ett filträd.
Textfiler & Binärfiler
Python hanterar två typer av filer, textfiler och binärfiler.
En textfil innehåller bara text och kan läsas och vara begriplig utan att använda något dataprogram. En textfil är strukturerad som en sekvens av rader. Och varje rad i textfilen består av en sekvens av tecken. Avslutning av varje rad i en textfil betecknas med slutet av raden (EOL = End Of Line). Det finns några specialtecken som används som EOL, men Carriage Return (CR) + Line Feed (LF) är det vanligaste.
En binärfil, är en fil som innehåller information som är avsett att läsas av datorprogram. Binärfiler kan normalt inte tolkas genom att se innehållet i filen. Exempel på binärfiler är t.ex. bild- och ljudfiler. Bildfiler som .jpg, .png, .gif, etc. och dokument som .docx, .xlsx, .pdf, etc., är alla binärfiler.
Grundprincipen för att läsa och/eller skriva filer är:
- Öppna en fil
- Läs eller skriv i filen
- Stäng filen
Öppna en fil
För att kunna läsa från eller skriva till en fil måste filen först öppnas. Det görs med funktionen open, som har en parameter som är sökvägen till filen som ska öppnas. Ligger filen i samma mapp som programmet så räcker det att ange filnamnet.
f = open("test.txt") # Open file in current directory
f = open("C:\\user\\readme.txt") # Open file specifying full path
Funktionen open returnerar ett filobjekt, med metoder som används för att läsa, ändra och stänga filen.
Det går att ange mode (läge) när vi öppnar en fil. I mode anges om filen ska läsas r, skrivas w
eller tecken läggas till a.
Vi kan också ange om vi vill öppna filen i textläge eller binärt läge.
| Mode | Beskrivning |
|---|---|
r | Read (default), öppnar en fil för läsning. Fel om filen inte existerar. |
w | Write, öppnar en fil för att skriva. Skapar en ny fil om den inte finns eller skriver över filen om den finns. |
a | Append, öppnar en fil för att lägga till i slutet av filen. Skapar en ny fil om den inte finns. |
x | Create, skapar en fil. Om filen redan finns returneras ett fel. |
t | Text, öppnas i textläge. (standard) |
b | Binary, öppnas i binärt läge. |
+ | Öppnar en fil för uppdatering (läsning och skrivning) |
f = open('test.txt', 'rt') # Opens textfile for reading, same as open('test.txt')
f = open('test.txt', 'rb') # Opens binary file for reading
f = open('test.txt', 'w') # Write in text mode
f = open('test.txt', 'wb') # Write in binary mode
f = open('img.png', 'r+') # Read and write in text mode
f = open('img.png', 'r+b') # Read and write in binary mode
Standard teckenkodningen när filer öppnas är utf-8, men det kan också anges när filen öppnas. Därför, när du arbetar med filer i textläge, rekommenderas det starkt att du anger kodningstypen.
f = open("test.txt", 'r', encoding = 'utf-8')
Stäng en fil
När koden arbetat färdigt med filen måste den stängas. Det talar om till operativsystemet att resurserna som är knutna till filen frigörs.
T.ex. om vi öppnar en fil för skrivning är den låst och inget annat program kan öppna den för skrivning tills vi stänger filen.
Metoden close() stänger filen.
f = open('test.txt', 'r', encoding = 'utf-8')
f.close() # Close file
f = open('C:\user\readme.txt', 'r', encoding = 'utf-8')
f.close() # Close file
Läsa filer
read() läser hela filens innehåll.
read(n) för att läsa högst n tecken från en textfil eller n bytes från en binärfil.
f = open('demofile.txt', 'r', encoding = 'utf-8')
str = f.read() # Reads the whole textfile and return it as a string
print(str)
f.close()
f = open('demofile.txt', 'r', encoding = 'utf-8')
str = f.read(5) # Return the 5 first characters of the file
print(str)
f.close()
readline() läser en rad från en textfil och returnerar en sträng.
readlines() läser alla rader från en texfil, dvs hela filen, och returnerar dem som en lista.
f = open('demofile.txt', 'r', encoding = 'utf-8')
str = f.readline() # Read a line from the text file and return it as a string
print(str)
f.close()
f = open('demofile.txt', 'r', encoding = 'utf-8')
list = f.readlines() # Read lines from the text file and return it as a list
print(list[0]) # Print the first line of code
f.close()
readline(n) läser en rad från en textfil och returnerar en sträng, men läser max n tecken.
readlines(n) läser alla rader från en texfil, dvs hela filen, och returnerar dem som en lista, men läser max n tecken.
f = open('demofile.txt', 'r', encoding = 'utf-8')
str = f.readline() # Read a line from the text file and return it as a string
print(str)
f.close()
f = open('demofile.txt', 'r', encoding = 'utf-8')
list = f.readlines() # Read lines from the text file and return it as a list
print(list[0]) # Print the first line of code
f.close()
Skriva till filer
För att kunna skriva till en fil behöver funktionen open() ett till argument.
Vill man skriva över innehållet i filen är det strängen 'w', vill man lägga till innehåll i slutet av filen är det strängen 'a'.
Man måste vara försiktig med 'w', för den kommer att skriva över det gamla innehållet om filen redan existerar.
Sedan används filobjektets metod write() användas för att skriva till filen.
open(filename, 'w', encoding = 'utf-8') skriver över eventuellt tidigare innehåll.
open(filename, 'a', encoding = 'utf-8') skriver i slutet av filen, dvs lägger till.
write(str) skriver strängen str till filen och returnera antalet skrivna tecken.
writelines(lst) skriver en lista med rader till filen.
writable() returnerar True om det går att skriva till filen, annars returneras False.
f = open('test.txt', 'w', encoding = 'utf-8')
f.write('Hello, World!') # Write Hello World! to the file
f.close()
f = open('test.txt', 'a', encoding = 'utf-8')
f.write('Now the file has more content!') # Append content to the file
f.close()
Skapa en fil
Använd funktionen open() med en av följande argument:
open(filename, 'x', encoding = 'utf-8') Create, skapar en fil, returnerar ett fel om filen redan finns.
open(filename, 'a', encoding = 'utf-8') Append, skapar en fil om den inte redan existerar.
open(filename, 'w', encoding = 'utf-8') Write, skapar en fil om den inte redan existerar.
f = open('test.txt', 'x', encoding = 'utf-8') # A new empty file is created
f.close()
Radera en fil
För att radera en fil måste modulen OS importeras och metoden os.remove() användas.
import os
os.remove('test.txt') # The file is deleted, but gives an error if the file does not exist
För att undvika fel, går det att kontrollera om filen existerar före den ska raderas.
import os
if os.path.isfile('test.txt'):
os.remove('test.txt')
else:
print('The file does not exist')
Filhantering
Förutom att radera filer finns fler metoder i modulen os för att hantera filer:
os.rmdir() raderar en hel mapp (katalog), som måste vara tom.
import os
os.rmdir('myfolder') # Remove the folder myfolder
os.rename() byter namn på en fil.
import os
os.rename('demofile.txt', 'test.txt') # Change filename from demofile.txt to test.txt
os.mkdir() skapar en ny katalog.
import os
os.mkdir('MyNewDirectory') # Create a new directory
Operativsystem har alltid en aktuell arbetskatalog.
Om en fil skapas med f = open('test.txt', 'x', encoding = 'utf-8') kommer filen skapas i den
aktuella arbetskatalogen.
Om en fil ska raderas med os.remove('test.txt') letar koden efter filen i den aktuella arbetskatalogen.
os.getcwd() returnerar den aktuella arbetskatalogen.
import os
print(os.getcwd()) # Print the current working directory
os.chdir() ändrar den aktuella arbetskatalogen.
import os
os.chdir('c:\\user\\tmp') # Change the working directory
os.path.isfile('c:\\user\\tmp\\test.txt') returnerar True om filen finns, annars returneras False.
import os
exist = os.path.isfile('c:\\user\\tmp\\test.txt') # Check if a file exist
os.path.dirname(__file__) returnerar katalogen där Python-koden som körs finns.
import os
path = os.path.dirname(__file__) # Get the script directory
Filposition
När man läser eller skriver till en fil finns det alltid en aktuell filposition, dvs där läsningen/skrivningen börjar. Man kan likna det vid var markören befinner sig när man t.ex. skriver i Word.
tell() returnerar den aktuella filpositionen.
seek(offset) ändrar filpositionen till offset bytes, med hänvisning till startpositionen (=0).
f = open('test.txt', 'w', encoding = 'utf-8')
pos = f.tell() # Get the current file position
print(pos)
f.close()
f = open('test.txt', 'w', encoding = 'utf-8')
pos = f.seek(0) # Bring file cursor to initial position
print(pos)
f.close()
Filer med felhantering
Efter att en fil öppnats och man är klar med alla operationer på filen måste man stänga filen. När filen stängs frigörs de resurser som var knutna till filen. Om en fil öppnas för skrivning kan ingen annan process öppna samma fil för skrivning.
f = open('test.txt', 'w', encoding = 'utf-8')
# Perform some file and other operations before closing the file...
f.close()
Denna metod är inte helt säker. Om ett undantagsfel (exception) inträffar när vi utför någon åtgärd med filen, avslutas koden utan att
stänga filen. Ett säkrare sätt är att använda try - finally.
try:
f = open("test.txt", encoding = 'utf-8')
# Perform some file and other operations before closing the file...
finally:
f.close()
På detta sätt garanteras att filen alltid stängs, även om ett undantagsfel skulle inträffa.
Ett bra sätt att stänga filen är att använda with-satsen.
Då behövs inte close()-metoden anropas utan filen stängs automatiskt när koden i with-satsen körts klart.
with open("test.txt", "r", encoding = 'utf-8') as f:
for line in f:
print(line)
Filen öppnas med with-satsen. Alla operationer som utförs mot filen är indenterade i with-satsen.
Python kommer automatiskt stänga filen när with-satsen tagit slut.
Att använda sig av with minimerar och förenklar koden och är därför att rekommendera i de flesta fall.
Vad händer om man försöker öppna en fil som inte finns?
filename = 'dummy-does-not-exist.txt'
with open(filename, "r", encoding = 'utf-8') as f:
contents = f.read()
ger utskriften
Traceback (most recent call last):
File "main.py", line 2, in <module>
with open(filename, "r", encoding = 'utf-8') as f:
FileNotFoundError: [Errno 2] No such file or directory: 'dummy-does-not-exist.txt'
Med defensiv kodning går det att kontrollera om filen existerar före man försöker öppna den.
import os
filename = 'dummy-does-not-exist.txt'
if os.path.isfile(filename) == True:
with open(filename, "r", encoding = 'utf-8') as f:
contents = f.read()
else:
print(f'Can't find the file {filename}')
Med undantagshantering kan man kontrollera alla möjliga fel som kan uppstå.
import sys, os
try:
# Check for a file on the same directory as the executing code
path = os.path.dirname(__file__)
filename = f'{path}\\dummy-does-not-exist.txt'
with open(filename, "r", encoding = 'utf-8') as f:
contents = f.read()
except FileNotFoundError:
print(f'Can't find the file {filename}')
except:
# Catch all type of exceptions
e = sys.exc_info()[0] # Get the error that caused the exception
print(f'Error: {e}')
Typiska fel som kan uppstå vid felhantering är:
Försöker öppna en fil som inte hittas eller existerar.
Försöker skriva fast hårddisken är full.
Försöker skapa en fil eller mapp som redan finns.
Försöker skriva till en fil som öppnats för bara läsning.
Försöker läsa från en fil som öppnats för bara skrivning.
Sammanfattning för textfiler
| Mode | Beskrivning |
|---|---|
f = open('test.txt', 'r', encoding = 'utf-8') |
Read (default), öppnar en fil för läsning. Fel om filen inte existerar. |
f = open('test.txt', 'r+', encoding = 'utf-8') |
Read och Write, öppnar en fil för läsning och skrivning. Fel om filen inte existerar. |
f = open('test.txt', 'w', encoding = 'utf-8') |
Write, öppnar en fil för skrivning. Skapar en ny fil om den inte finns eller skriver över filen om den finns. |
f = open(filename, 'x', encoding = 'utf-8') |
Create, skapar en fil, returnerar ett fel om filen redan finns. |
f = open(filename, 'a', encoding = 'utf-8') |
Append, skapar en fil om den inte redan existerar. |
f.close() |
Stänger filen. |
str = f.read() |
Läser hela filens innehåll, returnerar en sträng. |
str = f.read(n) |
Läser högst n tecken från en textfil, returnerar en sträng. |
str = f.readline() |
Läser en rad från en textfil, returnerar en sträng. |
str = f.readline(n) |
Läser en rad från en textfil, returnerar en sträng, men läser max n tecken. |
lst = f.readlines() |
Läser alla rader från en textfil, returnerar dem som en lista. |
lst = f.readlines(n) |
Läser alla rader från en textfil, returnerar dem som en lista, men läser max n tecken. |
n = f.write(str) |
Skriver strängen str till filen, returnera antalet skrivna tecken. |
f.writelines(lst) |
Skriver en lista med rader till filen. |
b = f.writable() |
Returnerar True om det går att skriva till filen, annars returneras False. |
n = f.tell() |
Returnerar den aktuella filpositionen. |
f.seek(offset) |
Ändrar filpositionen till offset tecken. Offset 0 är startpositionen. |
Sammanfattning filhantering
Alla funktioner nedan kräver att modulen os importeras, dvs att koden import os ska finnas i koden.
| Mode | Beskrivning |
|---|---|
b = os.path.isfile(filename) |
Returnerar True om filen finns, annars returneras False. |
b = os.path.isdir(filename) |
Returnerar True om katalogen finns, annars returneras False. |
b = os.path.exists(filename) |
Returnerar True om filen eller katalogen finns, annars returneras False. |
os.rmdir(dir) |
Raderar en hel katalog, som måste vara tom. |
os.rename(src_filename, dest_filename) |
Byter namn på en fil. |
os.mkdir(dir) |
Skapar en ny katalog. |
cwd = os.getcwd() |
Returnerar den aktuella arbetskatalogen. |
os.chdir(dir) |
Ändrar den aktuella arbetskatalogen. |
path = os.path.dirname(__file__) |
Returnerar katalogen där Python-koden som körs finns. |
Begrepp
Katalog: Mapp, används för att organisera filer.
Directory: Engelska namnet för katalog.
Textfil: Innehåller bara rader av text, kan läsas utan att använda något dataprogram.
Binärfil: Innehåller information som är avsett att läsas av datorprogram.
Filposition: Aktuell position där läsning/skrivning börjar.
Aktuell katalog: Operativsystem har alltid en mapp, som används om ingen mapp anges.
Arbetskatalog: Ett annat ord för aktuell katalog.
Current Working Directory: Engelska namnet på aktuell katalog.
Länkar
Övningar
- Skriv ett program som öppnar en textfil och skriver ut dess innehåll.
- Skriv ett program som öppnar en textfil och skriver ut dess innehåll, men med varje rads radnummer först.
- Skriv ett program som frågar användaren om ett filnamn och öppnar sedan filen och skriver ut dess innehåll.
-
Skapa en texfil som ser ut som:
1 Apa
2 Babian
3 Chinchilla
4 Dromedar
5 Elefant
Inlämningsuppgift
Omvänd fil
Läs in textfil, som ska ligga i samma katalog som Python-koden.
Använd os.path.dirname(__file__) för att öppna filer i samma mapp som py-filen.
Skapa en ny textfil, om filen redan finns ska den skrivas över.
Den nya textfilen ska också ligga i samma katalog som Python-koden.
Den skapade filen ska skrivas i omvänd ordning till den inlästa.
Exempel
Om den inlästa filen har innehållet:
Hejsan, hoppsan, programmering är kul!
Då ska den skapade filen få innehållet:
!luk rä gniremmargorp ,nasppoh ,nasjeH
Tänk på att kommentera och ha bra variabelnamn.
Koden ska följa PEP 8.
Extra
Läs in godtycklig textfil, som ska ligga i samma katalog som Python-koden.
Använd os.path.dirname(__file__) för att öppna filer i samma mapp som py-filen.
Ett tecken i taget ska läsas och sparas i en lämplig samling.
Skapa en ny textfil, om filen redan finns ska den skrivas över.
Den nya textfilen ska också ligga i samma katalog som Python-koden.
Läs de lagrade tecken från samlingen och skriv i den skapade filen.
Den skapade filen ska skrivas i omvänd ordning till den inlästa.
Använd with-satsen och ha undantagshantering i koden.