2011-01-13 12 views
8

Aparece un IOError que se muestra a continuación cuando intento abrir un nuevo archivo usando "open (fname, 'w +')". El mensaje de error completo está debajo.Excepción de Python IOError al crear un archivo largo

El archivo no existe, pero verifiqué utilizando "os.access (dir_name, os.W_OK)" y "os.path.exists (dir_name)" que el directorio principal para el archivo existe.

Me pregunto si el nombre del archivo es demasiado largo para Windows, o si estoy haciendo algo mal. Cualquier consejo sería apreciado. Muchas gracias.

mensaje de error:

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

Gracias. El límite supera los 260 caracteres. El artículo de MSDN menciona que podemos usar el prefijo "\\? \" Para el nombre de archivo largo, solo curiosidad si alguien sabe cómo puedo agregar el prefijo al nombre del archivo. Cuando trato de hacer una simple operación "+", obtengo un EOL de error al escanear una cadena entre comillas simples '. (fname = '\\? \' + fname) – AshD

+0

Use "\\\\? \\". Una cadena en bruto no funcionará en este caso. – cgohlke

+0

Usa barras diagonales en su lugar. También vea http://stackoverflow.com/faq#howtoask – Johnsyweb

Respuesta

7

En la API de Windows la longitud de trayectoria máxima está limitada a 260 caracteres.

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

Actualización: anteponer "\\? \" A la ruta.

+1

... combinado con el muy confuso valor de error; debería ser ENAMETOOLONG, no ENOENTAR. Creo que este es uno de esos errores oscuros de Windows que todos están confundidos por lo menos una vez en algún momento de su carrera. –

0

Si no es la longitud del nombre de archivo, que es el contenido del fichero ...

Python es el tratamiento de '\ 12' como una secuencia de control.

>>> 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 

Usando raw strings para nombres de archivo de Windows le ayudará:

>>> 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 

actualización

Como alternativa, utilizar barras inclinadas '/' en lugar de barras invertidas '\', ya que éstos funcionarán en todos sistemas operativos y le ahorrará molestias con barras invertidas justo al final de una ruta de acceso como en sus comentarios.

Véase también os.path.join().

Actualización 2

demostración simplificada del 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

Es mejor utilizar consistentemente barras diagonales; funcionan bien en Windows y resulta en código que es mucho más probable que funcione en otras plataformas. –

+1

El OP utilizó una ruta de archivo codificada correctamente. De lo contrario, el mensaje de error habría sido diferente (TypeError). – cgohlke

+0

@cgohlke: Consulte mi segunda actualización que muestra la excepción 'IOError' con el mismo texto que el OP reportado. – Johnsyweb

3

Aquí hay un código relacionado que funciona para mí (tengo nombres muy largos de archivo y rutas):

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') 
     ... 

Tenga en cuenta que para mí solo funcionaba con una combinación de todo lo siguiente:

  1. Prefijo '\\? \' En la parte delantera.

  2. Utilice la ruta completa, no la ruta relativa.

  3. Utilice solo barras diagonales inversas.

  4. En Python, la cadena de nombre de archivo debe ser una cadena unicode, por ejemplo u "abc", no "abc".

También tenga en cuenta, por alguna razón os.walk(..) devuelto algunos de los directorios como archivos, por lo que puedo comprobar por encima de eso.

+0

Muchas gracias por mencionar que la cadena de Python debe ser una cadena Unicode, ¡eso me salvó! –

+0

El 'os.getcwd()' lo arregló para mí. Tiene que ser todo el camino, no solo un camino relativo. – Blairg23

4

Puede mono parchear el archivo tar con este módulo:

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() 
Cuestiones relacionadas