Nombre de ruta demasiado largo para abrir?

Esta es una captura de pantalla de la ejecución:

Introduzca la descripción de la imagen aquí

Como ve, el error dice que el directorio “JSONFiles / Apartment / Rent / dubizzleabudhabiproperty” no está allí.

Pero mira mis archivos, por favor:

Introduzca la descripción de la imagen aquí

La carpeta está definitivamente allí.

Actualización 2

El código

self.file = open("JSONFiles/"+ item["category"]+"/" + item["action"]+"/"+ item['source']+"/"+fileName + '.json', 'wb') # Create a new JSON file with the name = fileName parameter line = json.dumps(dict(item)) # Change the item to a JSON format in one line self.file.write(line) # Write the item to the file 

ACTUALIZAR

Cuando cambio el nombre del archivo a uno más pequeño, funciona, por lo que el problema se debe a la longitud de la ruta. ¿Cuál es la solución por favor?

Las rutas de DOS MAX_PATH están limitadas a MAX_PATH (260) caracteres, incluido el carácter NUL terminación de la cadena. Puede superar este límite utilizando una ruta de longitud extendida que comienza con el prefijo \\?\ . Esta ruta debe ser una cadena Unicode, completamente calificada y solo debe utilizar la barra invertida como separador de ruta. Según la comparación de la funcionalidad del sistema de archivos de Microsoft, la longitud máxima de la ruta extendida es de 32760 caracteres. Un archivo individual o nombre de directorio puede tener hasta 255 caracteres (127 para el sistema de archivos UDF). Las rutas UNC extendidas también se admiten como \\?\UNC\server\share .

Por ejemplo:

 import os def winapi_path(dos_path, encoding=None): if (not isinstance(dos_path, unicode) and encoding is not None): dos_path = dos_path.decode(encoding) path = os.path.abspath(dos_path) if path.startswith(u"\\\\"): return u"\\\\?\\UNC\\" + path[2:] return u"\\\\?\\" + path path = winapi_path(os.path.join(u"JSONFiles", item["category"], item["action"], item["source"], fileName + ".json")) 
 >>> path = winapi_path("C:\\Temp\\test.txt") >>> print path \\?\C:\Temp\test.txt 

Vea las siguientes páginas en MSDN:

  • Nombrar archivos, rutas y espacios de nombres
  • Definición de un nombre de dispositivo de MS-DOS
  • Espacios de nombres de objetos del kernel

Fondo

Windows llama a la función de biblioteca de tiempo de ejecución de NT RtlDosPathNameToRelativeNtPathName_U_WithStatus para convertir una ruta de DOS a una ruta de NT nativa. Si open (es decir, CreateFile ) la ruta anterior con un punto de interrupción establecido en la última función, podemos ver cómo maneja una ruta que comienza con el prefijo \\?\ .

 Breakpoint 0 hit ntdll!RtlDosPathNameToRelativeNtPathName_U_WithStatus: 00007ff9`d1fb5880 4883ec58 sub rsp,58h 0:000> du @rcx 000000b4`52fc0f60 "\\?\C:\Temp\test.txt" 0:000> r rdx rdx=000000b450f9ec18 0:000> pt ntdll!RtlDosPathNameToRelativeNtPathName_U_WithStatus+0x66: 00007ff9`d1fb58e6 c3 ret 

El resultado reemplaza \\?\ Con el prefijo de dispositivos NT DOS \??\ , y copia la cadena en un UNICODE_STRING nativo:

 0:000> dS b450f9ec18 000000b4`536b7de0 "\??\C:\Temp\test.txt" 

Si usa //?/ lugar de \\?\ , Entonces la ruta aún está limitada a MAX_PATH caracteres. Si es demasiado largo, entonces RtlDosPathNameToRelativeNtPathName devuelve el código de estado STATUS_NAME_TOO_LONG (0xC0000106).

Si usa \\?\ Para el prefijo pero usa una barra diagonal en el rest de la ruta, Windows no traducirá la barra diagonal inversa para usted:

 Breakpoint 0 hit ntdll!RtlDosPathNameToRelativeNtPathName_U_WithStatus: 00007ff9`d1fb5880 4883ec58 sub rsp,58h 0:000> du @rcx 0000005b`c2ffbf30 "\\?\C:/Temp/test.txt" 0:000> r rdx rdx=0000005bc0b3f068 0:000> pt ntdll!RtlDosPathNameToRelativeNtPathName_U_WithStatus+0x66: 00007ff9`d1fb58e6 c3 ret 0:000> dS 5bc0b3f068 0000005b`c3066d30 "\??\C:/Temp/test.txt" 

La barra inclinada es un carácter de nombre de objeto válido en el espacio de nombres de NT. Está reservado por los sistemas de archivos de Microsoft, pero puede usar una barra inclinada en otros objetos del kernel con nombre, que se almacenan en \BaseNamedObjects o \Sessions\[session number]\BaseNamedObjects . Además, no creo que el administrador de E / S aplique la política de caracteres reservados en el dispositivo y los nombres de archivo. Depende del dispositivo. Tal vez alguien tenga un dispositivo Windows que implemente un espacio de nombres que permita una barra inclinada en los nombres. Como mínimo, puede crear nombres de dispositivos DOS que contengan una barra diagonal. Por ejemplo:

 >>> kernel32 = ctypes.WinDLL('kernel32') >>> kernel32.DefineDosDeviceW(0, u'My/Device', u'C:\\Temp') >>> os.path.exists(u'\\\\?\\My/Device\\test.txt') True 

Usted se estará preguntando qué \?? significa Esto solía ser un directorio real para enlaces de dispositivos DOS en el espacio de nombres de objetos, pero comenzando con NT 5 (o NT 4 con Terminal Services) se convirtió en un prefijo virtual. El administrador de objetos maneja este prefijo verificando primero los enlaces de los dispositivos DOS de la sesión de inicio de sesión en el directorio \Sessions\0\DosDevices\[LOGON_SESSION_ID] y luego verificando los enlaces de dispositivos DOS de todo el sistema en el \Global?? directorio.

Tenga en cuenta que la primera es una sesión de inicio de sesión, no una sesión de Windows. Los directorios de la sesión de inicio de sesión están todos bajo el directorio DosDevices de la sesión 0 de Windows (es decir, la sesión de servicios en Vista +). Por lo tanto, si tiene una unidad asignada para un inicio de sesión no elevado, descubrirá que no está disponible en un símbolo del sistema elevado, porque su token elevado es en realidad para una sesión de inicio de sesión diferente.

Un ejemplo de un enlace de dispositivo DOS es \Global??\C: => \Device\HarddiskVolume2 . En este caso, la unidad DOS C: es en realidad un enlace simbólico al dispositivo HarddiskVolume2 .

Aquí hay una breve descripción de cómo el sistema maneja el análisis de una ruta para abrir un archivo. Dado que estamos llamando WinAPI CreateFile, almacena el NT UNICODE_STRING NT en una estructura OBJECT_ATTRIBUTES y llama a la función del sistema NtCreateFile .

 0:000> g Breakpoint 1 hit ntdll!NtCreateFile: 00007ff9`d2023d70 4c8bd1 mov r10,rcx 0:000> !obja @r8 Obja +000000b450f9ec58 at 000000b450f9ec58: Name is \??\C:\Temp\test.txt OBJ_CASE_INSENSITIVE 

NtCreateFile llama a la función del administrador de E / S IoCreateFile , que a su vez llama a la API del administrador de objetos no documentados ObOpenObjectByName . Esto hace el trabajo de analizar el camino. El administrador de objetos comienza con \??\C:\Temp\test.txt . Luego reemplaza eso con \Global??\C:Temp\test.txt . A continuación, analiza hasta el enlace simbólico C: y tiene que volver a comenzar (repetir) la ruta final \Device\HarddiskVolume2\Temp\test.txt .

Una vez que el administrador de objetos llega al objeto de dispositivo HarddiskVolume2 , el análisis se transfiere al administrador de E / S, que implementa el tipo de objeto de Device . El ParseProcedure de un Device E / S crea el objeto de File y un paquete de solicitud de E / S (IRP) con el código de función principal IRP_MJ_CREATE (una operación de abrir / crear) para ser procesado por la stack de dispositivos. Esto se envía al controlador del dispositivo a través de IoCallDriver . Si el dispositivo implementa puntos de análisis (por ejemplo, puntos de assembly de unión, enlaces simbólicos, etc.) y la ruta contiene un punto de análisis, entonces la ruta resuelta debe enviarse nuevamente al administrador de objetos para que se analice desde el principio.

El controlador del dispositivo utilizará el SeChangeNotifyPrivilege (casi siempre presente y habilitado) del token de proceso (o subproceso si se hace pasar por una suplantación) para omitir las comprobaciones de acceso mientras se atraviesan directorios. Sin embargo, en última instancia, el acceso al dispositivo y al archivo de destino debe estar permitido por un descriptor de seguridad, que se verifique mediante SeAccessCheck . Excepto los sistemas de archivos simples como FAT32 no admiten la seguridad de archivos.

Puede haber varias razones para que obtenga este error. Por favor, asegúrese de lo siguiente:

  1. El directorio principal de la carpeta (archivos JSON) es el mismo que el directorio de la secuencia de comandos de Python.

  2. Aunque la carpeta existe, no significa que el archivo individual lo haga. Verifique lo mismo y asegúrese de que el nombre exacto del archivo coincida con el que intenta acceder su código Python.

Si aún enfrenta un problema, comparta el resultado del comando “dir” en la carpeta más interna a la que intenta acceder.