W3docs

Scrivere e creare file in Python

Impara a scrivere file in Python con write(), writelines(), modalità append, scritture binarie, pathlib, codifica e pattern sicuri con i blocchi with.

La scrittura di file è una delle operazioni di I/O più fondamentali in Python. Che si tratti di salvare l'output di un programma, persistere configurazioni, esportare dati in CSV o registrare eventi, è necessario un modo affidabile per creare e aggiornare file. Questo capitolo copre ogni approccio fornito da Python: write(), writelines(), modalità append, scritture binarie, gestione dei newline, codifica dei caratteri, la moderna API pathlib e i pattern per scrivere in modo sicuro senza perdita di dati.

Aprire un file per la scrittura

Ogni operazione di scrittura su file inizia con la funzione built-in open(). Il secondo argomento — la modalità — controlla cosa accade quando si apre il file:

ModalitàSignificatoFile esistenteFile mancante
"w"Scrittura (testo)Tronca (cancella) il fileCrea un nuovo file
"a"Append (testo)Sposta il puntatore alla fineCrea un nuovo file
"x"Creazione esclusivaSolleva FileExistsErrorCrea un nuovo file
"wb"Scrittura (binario)Tronca il fileCrea un nuovo file
"ab"Append (binario)Sposta il puntatore alla fineCrea un nuovo file
"r+"Lettura + scritturaApre nella posizione attualeSolleva FileNotFoundError

La cosa più importante da ricordare riguardo alla modalità "w": cancella silenziosamente l'intero file prima di scrivere. Se si desidera solo aggiungere contenuto a un file esistente, usare invece la modalità "a" (append).

Fornire sempre il parametro encoding quando si scrivono file di testo, in modo che il codice si comporti in modo identico su Windows, macOS e Linux:

file = open("output.txt", "w", encoding="utf-8")

Usare sempre un blocco with

Chiamare open() senza un blocco with significa dover chiamare file.close() manualmente. Dimenticarsi di chiudere un file porta a dati bufferizzati che non vengono mai scritti su disco, errori di troppi file aperti in script a lunga esecuzione e corruzione del file su alcuni sistemi operativi.

L'istruzione with (un context manager) risolve tutti questi problemi. Python chiude il file automaticamente quando il blocco termina — anche se viene sollevata un'eccezione all'interno del blocco.

with open("output.txt", "w", encoding="utf-8") as f:
    f.write("Hello, World!\n")
# File is closed and flushed here — guaranteed

Tutti gli esempi in questo capitolo usano l'istruzione with. Evitare il pattern manuale open() / close().

Scrivere testo con write()

file.write(string) scrive la stringa data nel file e restituisce il numero di caratteri scritti. Non aggiunge automaticamente un newline — occorre includere \n manualmente.

Scrivere una singola riga in un nuovo file

with open("greeting.txt", "w", encoding="utf-8") as f:
    chars_written = f.write("Hello, World!\n")
    print(chars_written)   # 14

Scrivere più righe chiamando write() ripetutamente

with open("poem.txt", "w", encoding="utf-8") as f:
    f.write("Roses are red,\n")
    f.write("Violets are blue,\n")
    f.write("Python is great,\n")
    f.write("And so are you.\n")

Ogni chiamata a write() aggiunge al file nella posizione corrente. Il file viene scritto da zero (qualsiasi contenuto precedente viene eliminato) perché è stata usata la modalità "w".

Scrivere più righe con writelines()

file.writelines(iterable) accetta qualsiasi iterabile di stringhe — una lista, un generatore o una tupla — e scrive ogni elemento in sequenza. Come write(), non aggiunge newline tra gli elementi.

Scrivere una lista di righe

lines = [
    "First line\n",
    "Second line\n",
    "Third line\n",
]

with open("lines.txt", "w", encoding="utf-8") as f:
    f.writelines(lines)

Se i dati sorgente non contengono già \n, aggiungerlo prima di scrivere:

data = ["Alice", "Bob", "Charlie"]

with open("names.txt", "w", encoding="utf-8") as f:
    f.writelines(name + "\n" for name in data)

L'espressione generatrice name + "\n" for name in data è efficiente in termini di memoria: Python produce ogni stringa su richiesta invece di costruire l'intera lista in memoria prima.

write() vs writelines() — Quando usare ciascuno

write()writelines()
InputUna singola stringaQualsiasi iterabile di stringhe
NewlineSi controlla ogni \nSi controlla ogni \n
Ideale perCostruire l'output in modo incrementaleScrivere una sequenza pre-costruita in una volta sola

Creare un file che non deve già esistere

Usare la modalità "x" (creazione esclusiva) quando si vuole che Python crei un nuovo file e fallisca se il file esiste già. Questo previene la sovrascrittura accidentale di dati importanti.

try:
    with open("config.txt", "x", encoding="utf-8") as f:
        f.write("host=localhost\n")
        f.write("port=8080\n")
except FileExistsError:
    print("config.txt already exists — not overwriting.")

Questo pattern è utile per generare file di output univoci (log, esportazioni, snapshot) dove una collisione indica che qualcosa è andato storto.

Aggiungere contenuto a un file esistente

Aprire un file con la modalità "a" sposta il puntatore di scrittura alla fine del file. Il nuovo contenuto viene aggiunto dopo quello esistente; nulla viene cancellato.

Aggiungere una voce di log a un file esistente

import datetime

with open("app.log", "a", encoding="utf-8") as f:
    timestamp = datetime.datetime.now().isoformat()
    f.write(f"[{timestamp}] Server started\n")

Se app.log non esiste ancora, Python lo crea. Se esiste, la nuova riga viene aggiunta alla fine. Eseguire lo script più volte accumula un log crescente.

Write vs Append — Scegliere la modalità giusta

  • Usare "w" quando si vuole sostituire interamente il contenuto del file (generare un report aggiornato, salvare una nuova configurazione).
  • Usare "a" quando si vuole aggiungere al contenuto esistente (logging, accumulo di risultati su più esecuzioni).

Newline e terminazioni di riga

La modalità testo di Python ("w", "a", "r") traduce il newline universale \n nella terminazione di riga nativa della piattaforma in scrittura:

  • Windows: \n\r\n (CRLF)
  • macOS / Linux: \n rimane \n (LF)

Questo è di solito il comportamento corretto — i file scritti su Windows si aprono correttamente in Notepad.

Se si ha bisogno di forzare una terminazione di riga specifica indipendentemente dalla piattaforma — ad esempio quando si generano file che devono essere letti da un sistema specifico — passare il parametro newline:

# Force Unix-style LF on all platforms (e.g. for Linux-target files)
with open("unix_file.txt", "w", encoding="utf-8", newline="\n") as f:
    f.write("line one\n")
    f.write("line two\n")

# Preserve line endings exactly as given (no translation at all)
with open("raw.txt", "w", encoding="utf-8", newline="") as f:
    f.write("line one\r\n")
    f.write("line two\n")

Codifica dei caratteri

Specificare sempre encoding= quando si scrivono file di testo. Fare affidamento sull'impostazione predefinita della piattaforma rischia di creare file che non possono essere letti su altri sistemi.

Codifiche consigliate per scenari comuni:

CodificaDa usare quando
"utf-8"Uso generale; funziona per tutte le lingue; predefinita per la maggior parte dei progetti Python
"utf-8-sig"UTF-8 con BOM — utile per file che verranno aperti in Excel su Windows
"latin-1"File legacy dell'Europa occidentale
"cp1252"Testo ANSI di Windows

Scrivere un file con codifica UTF-8

with open("international.txt", "w", encoding="utf-8") as f:
    f.write("English: Hello\n")
    f.write("Japanese: こんにちは\n")
    f.write("Arabic: مرحبا\n")

Scrivere file binari

Aprire un file con la modalità "wb" (write binary) per scrivere byte grezzi invece di stringhe. La modalità binaria è richiesta per immagini, audio, archivi compressi, eseguibili e qualsiasi dato non testuale. Non specificare encoding in modalità binaria.

Scrivere byte in un file binario

data = bytes([0x89, 0x50, 0x4E, 0x47])  # PNG magic bytes

with open("header.bin", "wb") as f:
    f.write(data)
    print(f.write(b"\r\n\x1a\n"))   # 4

Copiare un file binario

with open("photo.jpg", "rb") as src:
    content = src.read()

with open("photo_backup.jpg", "wb") as dst:
    dst.write(content)

Per file binari di grandi dimensioni, leggere e scrivere a blocchi per evitare di caricare l'intero file in memoria:

CHUNK = 65536  # 64 KB

with open("large.bin", "rb") as src, open("large_copy.bin", "wb") as dst:
    while True:
        chunk = src.read(CHUNK)
        if not chunk:
            break
        dst.write(chunk)

Gestire gli errori durante la scrittura

Uno script di qualità produttiva anticipa sempre i modi in cui una scrittura su file può fallire.

Gestire gli errori di scrittura più comuni

try:
    with open("/etc/protected.txt", "w", encoding="utf-8") as f:
        f.write("data\n")
except PermissionError:
    print("Error: you do not have write permission for this file.")
except FileNotFoundError:
    print("Error: one or more directories in the path do not exist.")
except IsADirectoryError:
    print("Error: the path points to a directory, not a file.")
except OSError as e:
    print(f"OS error: {e}")

Eccezioni comuni che si possono incontrare:

EccezioneQuando si verifica
PermissionErrorIl processo non ha i permessi di scrittura
FileNotFoundErrorUna directory intermedia nel percorso non esiste
FileExistsErrorModalità "x" e il file esiste già
IsADirectoryErrorIl percorso punta a una directory
OSErrorDisco pieno, errore del filesystem di rete e altri problemi a livello OS

Consultare Python Try Except per una guida completa alla gestione delle eccezioni.

Scrivere file in modo sicuro (pattern di scrittura atomica)

Un semplice open("file.txt", "w") non è sicuro per dati critici: se lo script si blocca o viene interrotto a metà scrittura, il file viene lasciato in uno stato parzialmente scritto e corrotto. La soluzione standard è una scrittura atomica: scrivere prima in un file temporaneo, poi rinominarlo sovrascrivendo il file di destinazione.

import os
import tempfile

def write_file_safely(path, content, encoding="utf-8"):
    """Write content to path atomically using a temp file + rename."""
    dir_name = os.path.dirname(os.path.abspath(path)) or "."
    # Write to a temp file in the same directory (same filesystem = atomic rename)
    fd, tmp_path = tempfile.mkstemp(dir=dir_name)
    try:
        with os.fdopen(fd, "w", encoding=encoding) as f:
            f.write(content)
        os.replace(tmp_path, path)   # atomic on POSIX; best-effort on Windows
    except Exception:
        os.unlink(tmp_path)          # clean up if something went wrong
        raise

write_file_safely("important.txt", "critical data\n")

os.replace() (Python 3.3+) sostituisce la destinazione in modo atomico sui sistemi POSIX: i lettori vedono il file vecchio o quello nuovo, mai una scrittura parziale.

Scrivere file con pathlib

pathlib.Path (introdotto in Python 3.4) fornisce un'API concisa e orientata agli oggetti. Per scritture semplici in un'unica operazione, Path.write_text() e Path.write_bytes() sono più leggibili di open().

Path.write_text()

from pathlib import Path

Path("output.txt").write_text("Hello from pathlib!\n", encoding="utf-8")

write_text() apre il file in modalità "w", scrive la stringa e chiude il file — tutto in una sola chiamata. Sovrascrive sempre il file. Non esiste un equivalente per l'append; per aggiungere contenuto usare open() con modalità "a".

Path.write_bytes()

from pathlib import Path

Path("data.bin").write_bytes(b"\x00\x01\x02\x03")

Costruire percorsi con pathlib

pathlib rende anche facile costruire percorsi in modo sicuro senza concatenazione di stringhe:

from pathlib import Path

output_dir = Path("results")
output_dir.mkdir(exist_ok=True)          # create the directory if needed

report_path = output_dir / "report.txt"
report_path.write_text("Run complete.\n", encoding="utf-8")

print(report_path)         # results/report.txt
print(report_path.exists())  # True

L'operatore / sugli oggetti Path unisce i segmenti del percorso — senza bisogno di os.path.join().

Esempio pratico: scrivere un report CSV

Il seguente esempio completo scrive una lista di record in un file CSV usando solo strumenti built-in (nessun modulo csv), dimostrando insieme diversi concetti trattati in questo capitolo.

from pathlib import Path
import datetime

def write_csv_report(path, headers, rows):
    """Write a simple CSV file with a header row."""
    with open(path, "w", encoding="utf-8", newline="") as f:
        f.write(",".join(headers) + "\n")
        for row in rows:
            f.write(",".join(str(v) for v in row) + "\n")

records = [
    ("Alice", 30, "Engineering"),
    ("Bob", 25, "Marketing"),
    ("Charlie", 35, "Finance"),
]

output = Path("staff_report.txt")
write_csv_report(output, ["Name", "Age", "Department"], records)

print(output.read_text(encoding="utf-8"))

Output atteso:

Name,Age,Department
Alice,30,Engineering
Bob,25,Marketing
Charlie,35,Finance

Notare che newline="" viene passato a open() in modo che Python non traduca doppiamente le terminazioni di riga nelle righe CSV — questo corrisponde alla raccomandazione nella documentazione del modulo csv di Python.

Per situazioni più complesse (quoting, dialetti, casi limite Unicode) usare il modulo built-in Python CSV.

Riferimento rapido

ObiettivoPattern di codice
Creare o sovrascrivere un fileopen("f.txt", "w", encoding="utf-8")
Aggiungere a un fileopen("f.txt", "a", encoding="utf-8")
Creare solo se nuovoopen("f.txt", "x", encoding="utf-8")
Scrivere dati binariopen("f.bin", "wb")
Scrivere una stringaf.write("text\n")
Scrivere una lista di stringhef.writelines(lines)
Scrittura testo in un'unica operazionePath("f.txt").write_text("...", encoding="utf-8")
Scrittura binaria in un'unica operazionePath("f.bin").write_bytes(b"...")
Scrittura sicura / atomicaScrivere in un file temporaneo, poi os.replace()

Capitoli correlati

Was this page helpful?