2013-01-24 39 views
12

Mi sembra di ricordare casi in lingue di livello inferiore che l'apertura di un file più di una volta in un programma potrebbe provocare un puntatore di ricerca condiviso. Di fare in giro in Python un po ', questo non sembra accadere per me:È sicuro aprire un file più volte contemporaneamente in Python?

$ cat file.txt 
first line! 
second 
third 
fourth 
and fifth 
>>> f1 = open('file.txt') 
>>> f2 = open('file.txt') 
>>> f1.readline() 
'first line!\n' 
>>> f2.read() 
'first line!\nsecond\nthird\nfourth\nand fifth\n' 
>>> f1.readline() 
'second\n' 
>>> f2.read() 
'' 
>>> f2.seek(0) 
>>> f1.readline() 
'third\n' 

È questo comportamento noto per essere sicuri? Sto facendo fatica a trovare una fonte che dice che va bene, e sarebbe di grande aiuto se potessi dipendere da questo.

Non vedo la posizione come un attributo dell'oggetto file, altrimenti avrei più fiducia in questo. So che potrebbe essere tenuto internamente nell'iteratore, ma idk come .tell() ci arriverebbe in quel caso.

>>> dir(f1) 
['__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__', 
'__init__', '__iter__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', 
'__setattr__', '__str__', 'close', 'closed', 'encoding', 'fileno', 'flush', 
'isatty', 'mode', 'name', 'newlines', 'next', 'read', 'readinto', 'readline', 
'readlines', 'seek', 'softspace', 'tell', 'truncate', 'write', 'writelines', 
'xreadlines'] 

UPDATE
A pagina 161 di The Python Essential Reference si afferma

Lo stesso file può essere aperto più di una volta nello stesso programma (o in programmi diversi). Ogni istanza del file aperto ha il proprio puntatore del file che può essere manipolato in modo indipendente.

così sembra infatti essere al sicuro, comportamento definito

+0

In python ogni volta che chiamate 'open()' crea un nuovo oggetto file (iteratore), quindi siete al sicuro. –

+1

Non conosco nessuna piattaforma in cui si possa avere un problema nel mantenere diversi puntatori di ricerca qui. Ma ... è accettabile per il tuo caso di utilizzo che il tuo codice possa generare un'eccezione aprendo 'f2' in alcuni casi su Windows, anche se non fallisce mai su Unix? – abarnert

+0

@abarnert Mi aspetto solo che questo venga eseguito su Windows e solo durante la lettura. L'apertura su Windows acquisirà normalmente blocchi esclusivi? –

risposta

7

su un sistema operativo moderno (post-1969 per UNIX-like sistemi operativi, o post-2000 per Windows, e probabilmente prima di questo, ma io sono contando Win2K come il primo "moderno" Windows), ogni istanza di un file aperto (descrittore di file) ha il proprio puntatore di ricerca. Non c'è magia nella classe di Python che farebbe in modo che le istanze condividano lo stato; file è un wrapper per un normale handle di file C, che a sua volta incapsula un descrittore di file OS e l'implementazione di file.tell() e file.seek() chiama le corrispondenti funzioni C stdio. (Per i dettagli disordinati vedi CPython fileobject.c.) Ci possono essere differenze tra il comportamento della libreria C e il comportamento del sistema operativo sottostante, ma in questo caso particolare questo non è un fattore.

Se si utilizza IronPython o Jython, utilizzerà l'oggetto file standard .Net o Java per l'implementazione sottostante, che a sua volta utilizzerà la libreria C standard o l'implementazione del sistema operativo.

Quindi il tuo approccio va bene a meno che tu non stia eseguendo in qualche modo Python su alcuni SO non standard con bizzarri comportamenti di I/O.

È possibile ottenere risultati imprevisti durante la scrittura se non si scarica in modo tempestivo; i dati possono rimanere in memoria per un po 'di tempo prima che colpisca effettivamente il disco ed è disponibile per gli altri descrittori di file che hai aperto sullo stesso file. Come sottolinea Abarnert in un commento, è comunque problematico, tranne che in casi molto semplici.

+0

Se apri tutti i file in sola lettura, il problema "flush" non si presenta mai. E se non apri tutti i file in sola lettura, avrai problemi più seri. – abarnert

+2

Ancora più importante, la maggior parte dei dettagli qui sono sbagliati. 'file' è _not_ un wrapper per un descrittore di file ordinario; è un wrapper per un 'FILE *'. E 'tell' e' seek' non chiamano direttamente attraverso le corrispondenti funzioni OS di basso livello; chiamano le corrispondenti funzioni 'stdio' di medio livello. E questo fa una grande differenza su Windows, perché le regole su come, ad esempio, il blocco dei file funziona in 'fopen' rispetto a' CreateFile' sono completamente differenti. – abarnert

+0

Grazie per le correzioni. – kindall

Problemi correlati