2011-01-13 10 views
8

Viene visualizzato un errore IOE di seguito quando si tenta di aprire un nuovo file utilizzando "open (fname, 'w +')". Il messaggio di errore completo è riportato di seguito.Eccezione IOError Python durante la creazione di un file lungo

Il file non esiste, ma ho verificato l'utilizzo di "os.access (dir_name, os.W_OK)" e "os.path.exists (dir_name)" che la directory principale per il file esiste.

Mi chiedo se il nome del file è troppo lungo per Windows o se sto facendo qualcosa di sbagliato. Qualsiasi consiglio sarebbe apprezzato. Grazie mille.

Messaggio di errore:

IOError: [Errno 2] No such file or directory: 'C:\Documents and Settings\Administrator\op_models\Corp_Network_Nov12\abcde_corporate_nov_12.project\abcde_corporate_nov_12-ctr.rptd.dir\ctr\Non Business Hours for Weeknights\hourly_data_for_2_weeks\1294897740\json.data\Link\0\Link Utilization\analyzer393146160-data0.js'

+0

Grazie. Il limite supera i 260 caratteri. L'articolo MSDN menziona che possiamo usare il prefisso "\\? \" Per il nome lungo del file, solo curioso se qualcuno sa come posso aggiungere il prefisso al nome del file. Quando provo a eseguire una semplice operazione "+", viene visualizzato un errore EOL durante la scansione di una stringa con quotatura singola ". (fname = '\\? \' + fname) – AshD

+0

Utilizzare "\\\\? \\". In questo caso una stringa non funzionante non funzionerà. – cgohlke

+0

Utilizzare invece le barre in avanti. Vedi anche http://stackoverflow.com/faq#howtoask – Johnsyweb

risposta

7

Nel API di Windows la lunghezza massima del percorso è limitata a 260 caratteri. Aggiornamento

http://msdn.microsoft.com/en-us/library/aa365247%28v=vs.85%29.aspx

: anteporre "\\? \" Al percorso.

+1

... combinato con il valore di errore molto confuso; dovrebbe essere ENAMETOOLONG, non ENOENT. Penso che questo sia uno di quegli oscuri bug di Windows che tutti sono stati confusi almeno una volta ad un certo punto della loro carriera. –

0

Se non è la lunghezza del nome del file, è il contenuto del nome del file ...

Python è trattare '\ 12' come una sequenza di controllo.

>>> fn='C:\Documents and Settings\Administrator\op_models\Corp_Network_Nov12\abcde_corporate_nov_12.project\abcde_corporate_nov_12-ctr.rptd.dir\ctr\Non Business Hours for Weeknights\hourly_data_for_2_weeks\1294897740\json.data\Link\0\Link Utilization\analyzer393146160-data0.js' 
>>> print fn 
C:\Documents and Settings\Administrator\op_models\Corp_Network_Nov12bcde_corporate_nov_12.projectbcde_corporate_nov_12-ctr.rptd.dir\ctr\Non Business Hours for Weeknights\hourly_data_for_2_weeks 
94897740\json.data\Link\Link Utilizationnalyzer393146160-data0.js 

Utilizzando raw strings per i nomi dei file di Windows vi aiuterà:

>>> fn=r'C:\Documents and Settings\Administrator\op_models\Corp_Network_Nov12\abcde_corporate_nov_12.project\abcde_corporate_nov_12-ctr.rptd.dir\ctr\Non Business Hours for Weeknights\hourly_data_for_2_weeks\1294897740\json.data\Link\0\Link Utilization\analyzer393146160-data0.js' 
>>> print fn 
C:\Documents and Settings\Administrator\op_models\Corp_Network_Nov12\abcde_corporate_nov_12.project\abcde_corporate_nov_12-ctr.rptd.dir\ctr\Non Business Hours for Weeknights\hourly_data_for_2_weeks\1294897740\json.data\Link\0\Link Utilization\analyzer393146160-data0.js 

Aggiornamento

In alternativa, utilizzare le barre '/' invece di backslash '\', dal momento che questi funzioneranno su tutti sistemi operativi e ti farà risparmiare fastidi con backslash proprio alla fine di un percorso come nei tuoi commenti.

Vedere anche os.path.join().

Update 2

dimostrazione semplice problema:

>>> open('.\12\n\r\file.txt') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
IOError: [Errno 2] No such file or directory: '.\n\n\r\x0cile.txt' 
>>> open('./12/n/r/file.txt') 
<open file './12/n/r/file.txt', mode 'r' at 0x7ff83f98> 

C:\Users\johnysweb>copy .\12\n\r\file.txt con 
Blah 
     1 file(s) copied. 
+2

Stai meglio usare in modo coerente le barre; funzionano bene in Windows e risultano in un codice che è molto più probabile che funzioni su altre piattaforme. –

+1

L'OP ha utilizzato un percorso file correttamente codificato. Altrimenti il ​​messaggio di errore sarebbe stato diverso (TypeError). – cgohlke

+0

@cgohlke: Si prega di consultare il mio secondo aggiornamento che dimostra l'eccezione 'IOError' con lo stesso testo dell'OP riportato. – Johnsyweb

3

Ecco alcuni relativo codice che funziona per me (ho i nomi di file molto lungo e percorsi):

for d in os.walk(os.getcwd()): 
    dirname = d[0] 
    files = d[2] 
    for f in files: 
     long_fname = u"\\\\?\\" + os.getcwd() + u"\\" + dirname + u"\\" + f 
     if op.isdir(long_fname): 
      continue 
     fin = open(long_fname, 'rb') 
     ... 

Nota che per me ha funzionato solo con una combinazione di tutti i seguenti elementi:

  1. Prepend "\\? \" Nella parte anteriore.

  2. Usa percorso completo, percorso non relativo.

  3. Utilizzare solo barre inverse.

  4. In Python, la stringa del nome file deve essere una stringa unicode, ad esempio u "abc", non "abc".

Notare inoltre, per qualche motivo os.walk(..) restituito alcune delle directory come file, così sopra verifico per questo.

+0

Grazie mille per aver detto che la stringa Python deve essere una stringa Unicode - che mi ha salvato! –

+0

Il 'os.getcwd()' l'ha risolto per me. Deve essere l'intero percorso, non solo un percorso relativo. – Blairg23

4

È possibile scimmia patchare il modulo tarfile con questo:

import tarfile 

def monkey_patch_tarfile(): 
    import os 
    import sys 
    if sys.platform not in ['cygwin', 'win32']: 
     return 
    def long_open(name, *args, **kwargs): 
    # http://msdn.microsoft.com/en-us/library/aa365247%28v=vs.85%29.aspx#maxpath 
     if len(name) >= 200: 
      if not os.path.isabs(name): 
       name = os.path.join(os.getcwd(), name) 
      name = "\\\\?\\" + os.path.normpath(name) 
     return long_open.bltn_open(name, *args, **kwargs) 
    long_open.bltn_open = tarfile.bltn_open 
    tarfile.bltn_open = long_open 

monkey_patch_tarfile()