Pra*_*ala 2 python windows shutil pandas spyder
我正在尝试用 pandas 读取 Excel 文件。
df=pd.read_excel('abcd (xyz-9) Interim Report 01-03-18.xlsx')
Run Code Online (Sandbox Code Playgroud)
这给了我文件未找到错误。如果我删除括号并将文件重命名为'abcd Interim Report 01-03-18.xlsx',那么它就可以正常工作。
我尝试用shutil重命名,但它给了我同样的错误
shutil.copyfile('abcd (xyz-9) Interim Report 01-03-18.xlsx','test.xlsx')
Run Code Online (Sandbox Code Playgroud)
我试过
1. pd.read_excel('abcd ^(xyz-9) Interim Report 01-03-18.xlsx')
2. pd.read_excel('abcd \\(xyz-9\\) Interim Report 01-03-18.xlsx')
Run Code Online (Sandbox Code Playgroud)
编辑:
即使我将 cwd 更改为文件位置,该文件似乎可以在本地驱动器上运行,但不能在网络驱动器上运行。
关于使用 glob 和os.path.exists:
df=pd.read_excel('abcd (xyz-9) Interim Report 01-03-18.xlsx')
Run Code Online (Sandbox Code Playgroud)
shutil.copyfile('abcd (xyz-9) Interim Report 01-03-18.xlsx','test.xlsx')
Run Code Online (Sandbox Code Playgroud)
关于使用 glob 和os.stat:
1. pd.read_excel('abcd ^(xyz-9) Interim Report 01-03-18.xlsx')
2. pd.read_excel('abcd \\(xyz-9\\) Interim Report 01-03-18.xlsx')
Run Code Online (Sandbox Code Playgroud)
for i in range(0,1):
for filename in glob.glob(fpath+"\\"+ldir[i]+"\\"+"*Interim*.xlsx"):
print(filename)
print(os.path.exists(filename))
Run Code Online (Sandbox Code Playgroud)
测试os.stat显示,访问带括号的路径会失败,并显示ERROR_PATH_NOT_FOUND(3),这可能是路径组件丢失或路径太长。我们知道找到最终路径分量不是问题,因为在这种情况下我们预计错误为ERROR_FILE_NOT_FOUND(2)。我们知道这不是保留字符的问题,因为在这种情况下我们预计错误是ERROR_INVALID_NAME(123)。另外,在这两种情况下,Windows API 都必须进行 NT 系统调用,但我们看到最后的 NT 状态是STATUS_NO_MORE_FILES(0x80000006),这是os.listdir来自glob.glob. 因此,问题很可能是路径太长。
为了简洁或隐私,问题似乎将某些路径组件名称缩短为“xxx”。如果扩展到真实名称,我们可能会看到带有“(xyz-9)”的路径至少有 260 个字符,这比 DOS 路径允许的最大长度(MAX_PATH - 1259 个字符)多 1 个字符。
我们可以通过将长路径转换为扩展路径来访问长路径,扩展路径是一个以“\\?\”设备路径前缀开头的 Unicode 字符串,或者以“\\?\UNC\”开头的 UNC 路径。首先,由于 Windows 中的字节路径仅限于MAX_PATH字符,因此我们必须将字节路径解码为 Unicode。接下来,我们必须规范化并限定路径 via os.path.abspath,因为扩展路径在访问时会绕过规范化。下面是一个extpath将 DOS 路径转换为扩展路径的函数:
import os
try:
from os import fsdecode
except ImportError: # Probably Python 2.x
import sys
def fsdecode(filename):
if isinstance(filename, type(u'')):
return filename
elif isinstance(filename, bytes):
return filename.decode(sys.getfilesystemencoding(), 'strict')
raise TypeError('expected string, not {}'.format(
type(filename).__name__))
def extpath(path):
path = os.path.abspath(fsdecode(path))
if not path.startswith(u'\\\\?\\'):
if path.startswith(u'\\\\.\\'):
path = u'\\\\?\\' + path[4:]
elif path.startswith(u'\\\\'):
path = u'\\\\?\\UNC\\' + path[2:]
else:
path = u'\\\\?\\' + path
return path
Run Code Online (Sandbox Code Playgroud)
背景
Windows NT(即自XP以来的所有Windows版本)的核心是NTOS操作系统,它使用NT内核。这类似于 20 世纪 80 年代和 90 年代初将 16 位 Windows 分层到 DOS 之上的方式。但 NTOS 比 DOS 与 Windows 的耦合更紧密,而且它是一个功能更强大的操作系统(例如,支持对称多处理、抢占式多线程、虚拟内存、异步 I/O、安全对象以及同时登录和会话的多个用户)。
在某些方面,Windows 仍然保留其 MS-DOS 根源。特别是,对于磁盘设备和文件系统路径,Windows API 使用 DOS 路径而不是 NT 对象路径。这包括 DOS 驱动器“A:”到“Z:”以及 UNC 路径,例如“\\server\share\path”。Windows API 标准化 DOS 路径,用反斜杠替换正斜杠;使用进程工作目录或每个驱动器工作目录解析相对路径(即没有根目录或没有驱动器的路径);解决 ”。” 和“..”组件;并修剪最终组件中的尾随空格和点。
当访问 DOS 路径时,Windows 会将其转换为以 WINAPI 设备前缀之一“\\.\”和“\\?\”开头的设备路径(例如“C:\Windows”->“\\?”)。 \C:\Windows")。对于驱动器盘符路径和相对路径(但不是 UNC 路径),它在最终路径组件中保留一小组 DOS 设备名称(例如“C:\Temp\con”->“\\.\con”,以及“nul”->“\\.\nul”)。对于UNC 路径,它使用“UNC”设备安装点(例如\\server\share\path -> “\\?\UNC\server\share\path”)。在呼叫传递到 NT 域之前,WINAPI 设备前缀(“\\.\”或“\\?\”)将替换为 NTAPI 设备前缀(“\??\”)。
这些设备名称空间前缀是 NT 对象名称空间中调用者的本地安装点目录的简写(即“\Sessions\0\DosDevices\<调用者的登录会话 ID>”)。本地安装点目录隐式地隐藏全局安装点目录(即“\Global??”)。例如,“C:\Temp”变为“\??\C:\Temp”,如果全局“C:”没有本地阴影,则其计算结果为“\Global??\C:\Temp”。全局安装点可以通过“Global”对象链接(例如“\\?\Global\C:\Temp”)显式引用,该链接应该始终可用。
通常,DOS 路径规范化使用空间不超过MAX_PATH(260) 个字符的字符串缓冲区。在 Windows 10 中,如果为系统启用了长路径并且应用程序清单声明它支持长路径,则(在大多数情况下)会解除此旧限制。Python 3.6+ 中的“python[w].exe”可执行文件具有此清单设置。
如果未启用长 DOS 路径,大多数文件 API 函数仍然支持长路径。我们只需使用以“\\?\”前缀开头的WINAPI设备路径,这称为扩展路径。这类似于以“\\.\”前缀开头的常规设备路径,但扩展路径在访问时不会标准化。缺点是我们必须实现自己的路径标准化。在 Python 中,这是由os.path.abspath. 我们仍然需要手动重写 UNC 路径,但这很简单,只需将前导“\\”替换为“\\?\UNC\”即可。
请注意,工作目录不支持设备路径,无论是否扩展。如果我们将设备路径设置为工作目录,系统将出现未定义的行为。因此,不要将它们与 Pythonos.chdir或cwd的参数一起使用subprocess.Popen。这意味着我们无法通过将扩展路径设置为工作目录来绕过使用长相对路径的限制。在 Windows 10 中,如果为进程启用了长 DOS 路径,则工作目录确实支持长路径,但它仍然只支持常规 DOS 路径(UNC 和驱动器盘符路径),而不支持设备路径。