gpt4 book ai didi

python - 路径名打开时间太长?

转载 作者:可可西里 更新时间:2023-11-01 13:28:07 25 4
gpt4 key购买 nike

这是执行的屏幕截图:

Enter image description here

如您所见,该错误表明目录“JSONFiles/Apartment/Rent/dubizzleabudhabiproperty”不存在。

但是请查看我的文件:

Enter image description here

该文件夹肯定在那里。

更新2

代码

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

更新

当我将文件名更改为较小的文件名时,它可以工作,因此问题出在路径长度上。请问如何解决?

最佳答案

常规DOS路径限制为MAX_PATH(260)字符,包括字符串的终止NUL字符。您可以使用以\\?\前缀开头的扩展长度路径来超过此限制。此路径必须是完全合格的Unicode字符串,并且只能将反斜杠用作路径分隔符。按照Microsoft的file system functionality comparison,最大扩展路径长度为32760个字符。单个文件或目录名称最多可包含255个字符(对于UDF文件系统,则为127个字符)。扩展的UNC路径也支持作为\\?\UNC\server\share

例如:

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

请在MSDN上查看以下页面:
  • Naming Files, Paths, and Namespaces
  • Defining an MS-DOS Device Name
  • Kernel object namespaces


  • 背景

    Windows调用NT运行时库函数 RtlDosPathNameToRelativeNtPathName_U_WithStatus将DOS路径转换为本地NT路径。如果我们在上面的路径中使用 open(即 CreateFile)在后一个函数上设置了断点,则可以看到它如何处理以 \\?\前缀开头的路径。

    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

    结果用NT DOS设备前缀 \\?\替换 \??\,并将字符串复制到本地 UNICODE_STRING :

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

    如果您使用 //?/而不是 \\?\,那么该路径仍限于 MAX_PATH字符。如果太长,则 RtlDosPathNameToRelativeNtPathName返回状态码 STATUS_NAME_TOO_LONG(0xC0000106)。

    如果您使用 \\?\作为前缀,但在其余路径中使用斜杠,则Windows不会为您将斜杠转换为反斜杠:

    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"

    正斜杠是NT namespace 中的有效对象名称字符。它由Microsoft文件系统保留,但是您可以在其他命名的内核对象中使用正斜杠,这些对象存储在 \BaseNamedObjects\Sessions\[session number]\BaseNamedObjects中。另外,我认为I/O管理器不对设备和文件名中的保留字符强制执行该策略。这取决于设备。也许有人在那里有一个Windows设备,该设备实现了一个 namespace ,该 namespace 允许名称中的正斜杠。至少您可以创建包含正斜杠的DOS设备名称。例如:

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

    您可能想知道 \??代表什么。这曾经是对象 namespace 中DOS设备链接的实际目录,但是从NT 5(或带有终端服务的NT 4)开始,它成为了虚拟前缀。对象管理器通过首先检查目录 \Sessions\0\DosDevices\[LOGON_SESSION_ID]中的登录 session 的DOS设备链接,然后检查 \Global??目录中的系统范围的DOS设备链接来处理此前缀。

    请注意,前者是登录 session ,而不是Windows session 。登录 session 目录均位于Windows session 0(即Vista +中的服务 session )的 DosDevices目录下。因此,如果您有一个用于非提升登录的映射驱动器,您会发现它在提升的命令提示符中不可用,因为提升的 token 实际上是用于其他登录 session 的。

    DOS设备链接的一个示例是 \Global??\C: => \Device\HarddiskVolume2。在这种情况下,DOS C:驱动器实际上是到 HarddiskVolume2设备的符号链接(symbolic link)。

    这是系统如何处理解析路径以打开文件的简要概述。假设我们正在调用WinAPI CreateFile,它将翻译后的NT UNICODE_STRING存储在 OBJECT_ATTRIBUTES 结构中,并调用系统函数 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调用I/O管理器函数 IoCreateFile ,该函数又调用未记录的对象管理器API ObOpenObjectByName。这完成了解析路径的工作。对象管理器以 \??\C:\Temp\test.txt开头。然后,将其替换为 \Global??\C:Temp\test.txt。接下来,它解析到 C:符号链接(symbolic link),并且必须重新开始(解析)最终路径 \Device\HarddiskVolume2\Temp\test.txt

    一旦对象管理器到达 HarddiskVolume2设备对象,解析就会移交给I/O管理器,后者将实现 Device对象类型。 I/O ParseProcedureDevice创建 File对象和带有 I/O Request Packet (IRP) IRP_MJ_CREATEmajor function code(打开/创建操作),以供设备堆栈处理。这通过 IoCallDriver 发送到设备驱动程序。如果设备实现了重新解析点(例如,结点安装点,符号链接(symbolic link)等),并且该路径包含一个重新解析点,则必须将解析后的路径重新提交给对象管理器,以便从头开始解析。

    设备驱动程序将使用进程 token (或线程,如果是模拟的)的 SeChangeNotifyPrivilege(几乎始终存在并启用)在遍历目录时绕过访问检查。但是,最终必须通过安全描述符允许访问设备和目标文件,该描述符已通过 SeAccessCheck 进行了验证。除了简单的文件系统(例如FAT32)不支持文件安全性。

    关于python - 路径名打开时间太长?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36219317/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com