检查字符串是否为合法文件路径-Python3

在 Python3 中如何检查一个字符串能否成为文件路径?即使这个文件现在还不存在,但当你要按路径创建时它能创建成功。显然 os.isdir() 等函数不能满足我们的要求,因为 os.isdir() 要求文件已经存在。我的笔记将解决这个问题。

定义“合法”

什么样的路径是合法的呢?一般来说,合法有效的文件路径有以下几点: 1. 不包含空字节(即 Python 中的 )。这是所有 POSIX 兼容文件系统的硬性要求。 2. 路径中不含有超过 255 个字符(<=255)的组件,简单来说就是文件夹和文件的名字不超过 255 个字符 3. 在 Windows 中文件路径的根会是一个驱动器(比如:C: ) 4. 在 POSIX 中文件路径的根会是根目录 ( / )

实现目标

  1. 检验字符串的合法性
  2. 避免不必要的写入,即先试图创建文件再校验的实现方式
  3. 在路径位于慢速驱动器时依旧能快速检验,以防止多次检验造成的卡顿(比如将网络挂载为驱动器进行访问)

一些 Python 知识

os.stat() 和 os.lstat()

获取文件或文件描述符的状态。在所给路径上执行等效于 stat() 系统调用的操作。path 可以是字符串类型,或(直接传入或通过 PathLike 接口间接传入的) bytes 类型,或打开的文件描述符。返回一个 stat_result 对象。—— Python 3.11.1 文档

在给定路径上执行本函数,其操作相当于 lstat() 系统调用,类似于 stat() 但不跟踪符号链接。返回值是 stat_result 对象。在不支持符号链接的平台上,本函数是 stat() 的别名。从 Python 3.3 起,此功能等价于 os.stat(path, dir_fd=dir_fd, follow_symlinks=False)。 —— Python 3.11.1 文档

但我们的目标不是这个,我们的目标是它将会抛出的异常: 1. FileNotFoundError :如果路径组件不存在 2. TypeError :路径存在,但包含空字节 3. OSError :路径存在,但字符长度超过 255 字节 4. winerror : 在 Windows 下,winerror 属性为 123 (即 ERROR_INVALID_NAME )文件名、目录名或卷标语法不正确

比如 /etcc/aaaaa....aaaa (256 个 a 且不存在 etcc 目录 ) 会抛出 FileNotFoundError 但 /etc/aa....aaa (256 个 a 且存在 etc 目录) 会抛出 OSError

总结一下,lstat() 会优先检查路径是否存在,然后是文件是否存在。注意,目录或者说文件夹也是文件。也就是说,我们保证路径存在就可以检查文件的合法性。

算法规划

  1. 将路径拆分为路径组件('/etc/apt/' 变成 ['etc','apt'])
  2. 在一定存在且访问迅速的路径下调用 os.stat() 对路径判断。根目录或%HOMEDRIVE%(Windwos 安装的驱动器,比如 C:)是一个不错的选择(os.stat('/'+'etc'))
  3. 不停尝试,利用分治的思想,部分合法组成的大问题也合法

开始实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import errno,os,sys

def IsPathnameValid(pathname:str)->bool:
"""检验传入的字符串是否为文件路径

Args:
pathname (str): 可能是文件路径的字符串

Returns:
bool: True 为符合
"""
ERROR_INVALID_NAME = 123
try:
if not isinstance(pathname,str) or not pathname:
return False

_,pathname=os.path.splitdrive(pathname)

root_dirname=os.environ.get('HOMEDRIVE','C:') if sys.platform=='win32' else os.path.sep
assert os.path.isdir(root_dirname)

root_dirname=root_dirname.strip(os.path.sep)+os.path.sep

for pathname_part in pathname.split(os.path.sep):
try:
os.lstat(root_dirname+pathname_part)

except OSError as exc:
if hasattr(exc,'winerror'):
if exc.winerror==ERROR_INVALID_NAME:
return False
elif exc.errno in {errno.ENAMETOOLONG,errno.ERANGE}:
return False
except TypeError as exc:
return False
else:
return True

来源

https://stackoverflow.com/questions/9532499/check-whether-a-path-is-valid-in-python-without-creating-a-file-at-the-paths-ta/9532586#9532586


检查字符串是否为合法文件路径-Python3
https://blog.hydrogenroom.icu/post/a0f6072d.html
作者
Hydrogen
发布于
2023年2月13日
许可协议