
Du ska kopiera en bild, konfigurationsfil eller export från ett Python-skript, men en enda felvald funktion kan skriva över fel fil eller lämna rättigheter bakom sig. För en vanlig fil fungerar oftast shutil.copy2() bra, även om den inte kan bevara all metadata på varje system.
Välj kopieringsfunktion efter vad målet behöver
copyfile()kopierar innehållet till ett angivet filnamn.copy()kopierar innehåll och behörighetsläge och kan ta emot en målmapp.copy2()försöker även bevara filmetadata, till exempel ändringstid.copytree()är funktionen för hela mappar och deras innehåll.- Kontrollera målet om en befintlig fil inte får skrivas över.
En rad med shutil räcker för en vanlig fil
Om en fil ska få en kopia med samma namn i en annan mapp är shutil.copy2() en smidig start. Modulens funktioner ingår i Pythons standardbibliotek, så ingen separat installation behövs.
from pathlib import Path
import shutil
source = Path("bilder/original.png")
destination = Path("public/kopia.png")
shutil.copy2(source, destination)Path gör sökvägarna tydligare, medan copy2() utför själva kopieringen. Målkatalogen måste redan finnas; om den saknas kan du skapa den först med destination.parent.mkdir(parents=True, exist_ok=True). Det är en liten förberedelse som ofta förebygger ett vanligt körfel.
copyfile, copy och copy2 lämnar olika resultat
Två kopior kan ha identiskt innehåll men ändå skilja sig i behörigheter och tidsstämplar. Därför tycker jag att valet ska styras av vad kopian faktiskt används till, inte av vilken funktion som råkar vara kortast.
| Funktion | Kopierar | Passar när |
|---|---|---|
shutil.copyfile(src, dst) | Filinnehåll | Du anger hela målfilens sökväg och bara innehållet behöver kopieras. |
shutil.copy(src, dst) | Filinnehåll och behörighetsläge | Målet kan vara en mapp eller ett filnamn. |
shutil.copy2(src, dst) | Som copy(), med försök att bevara mer metadata | Ändringstid och annan tillgänglig filmetadata bör följa med. |
En viktig detalj gömmer sig i ordet ”försöker”: copy2() kan inte bevara all metadata, och vad som går att kopiera beror på operativsystemet. Pythons dokumentation för shutil beskriver skillnaderna; exempelvis följer ägare och grupp inte med på POSIX-system. Om kopian ska användas som fullständig systembackup behöver du alltså kontrollera vilka metadata som faktiskt krävs.
Välj funktion efter mål och metadata
Det går att fatta beslutet utan att gissa: börja med måltypen och avgör sedan om filens metadata måste följa med. Tabellen visar vad du kan göra i de vanligaste lägena.
| Situation | Trolig orsak eller följd | Gör så här |
|---|---|---|
| Du anger en målmapp | copy() och copy2() kan kopiera dit med källans filnamn. | Använd någon av dem och kontrollera om metadata behövs. |
| Du anger ett nytt fullständigt filnamn | copyfile() kopierar innehållet dit, men inte filens behörighetsläge. | Välj copyfile() om innehållet räcker. |
| Ändringstid och behörighetsläge ska följa med | copy2() bevarar mer metadata än copyfile(), men stödet varierar. | Välj copy2() och verifiera metadata om programmet är beroende av dem. |
| Destinationen kan redan innehålla en fil med samma namn | Kopieringsfunktionerna kan skriva över den befintliga filen. | Kontrollera målet före kopieringen eller välj ett nytt filnamn. |
| Källa och mål pekar på samma fil | Kopieringen avbryts med SameFileError. | Jämför sökvägarna eller hantera undantaget. |
Om ett fel ska stoppa programmet kan kopieringen ligga i ett try-block som fångar exempelvis FileNotFoundError och PermissionError. Undvik att fånga alla fel utan åtskillnad: då riskerar ett verkligt problem att se ut som en lyckad kopiering.
En målmapp är inte samma sak som en fullständig backup
Om uppgiften gäller många filer i en katalog är shutil.copytree() den särskilda funktionen för att kopiera en hel mappstruktur. Den kopierar undermappar rekursivt och använder som standard copy2() för enskilda filer.
import shutil
shutil.copytree("projekt", "projekt_kopia")Som standard måste målmappen inte redan finnas. Med dirs_exist_ok=True kan en befintlig målmapp användas, men motsvarande filer i den kan då skrivas över. Jag skulle bara slå på det när det är avsikten; för en säkerhetskopia är en ny, tydligt namngiven målmapp ofta lättare att granska i efterhand.
För filer som kommer från en extern källa ska sökvägen dessutom valideras innan den används. En fil som oväntat hamnar utanför den avsedda målmappen är ett större problem än ett kopieringsfel.
Gör kopian spårbar innan skriptet körs automatiskt
När ett skript kopierar filer regelbundet är det lätt att missa att en körning skrev över gårdagens resultat. Börja med att bestämma om befintliga filer får ersättas, och lägg sedan till en enkel kontroll före anropet.
if not source.is_file():
raise FileNotFoundError(f"Källfilen saknas: {source}")
if destination.exists():
raise FileExistsError(f"Målfilen finns redan: {destination}")
shutil.copy2(source, destination)Den kontrollen gör utfallet tydligt, men den garanterar inte att filen blir en komplett backup med alla systemmetadata. För en vanlig kopia mellan projektmappar räcker copy2() ofta långt; för återställning av ett system bör kopieringskraven även omfatta behörigheter, ägarskap och andra attribut som Python inte alltid kan föra över.