NumPy 新改进:`DataSource` 与 `Repository` 全面支持 `os.PathLike` 路径对象

NumPy 新改进:`DataSource` 与 `Repository` 全面支持 `os.PathLike` 路径对象 科学计算数据分析【免费下载链接】numpyThe fundamental package for scientific computing with Python.项目地址https://gitcode.com/gh_mirrors/nu/numpy点击查看免费下载导读本篇文章聚焦 NumPy 近期一项面向日常数据文件操作的改进numpy.lib._datasource.DataSource与Repository类以及模块级numpy.lib._datasource.open辅助函数此前只接受字符串形式的本地路径如今在open、exists、abspath等核心方法中同样接受os.PathLike对象如pathlib.Path实例。读完本文你将了解该改动的背景、受影响的 API 清单、底层实现机制以及如何在科学计算脚本中直接用Path对象读写本地与远程数据文件。该改进源自 doc/release/upcoming_changes/31906.improvement.rst本文在忠实还原其内容的基础上结合_datasource模块源码与其测试用例进行深度展开。一、改动背景字符串路径的历史包袱_datasource模块是 NumPy 中负责本地 远程数据文件访问的统一文件接口其模块文档描述如下The goal of datasource is to abstract some of the file system operations when dealing with data files so the researcher doesnt have to know all the low-level details. Through datasource, a researcher can obtain and use a file with one function call, regardless of location of the file.即无论数据文件位于本地磁盘、http/ftp 远程服务器还是 gzip/bz2/xz 压缩包中调用者都可以用一次函数调用拿到可用的文件对象无需关心底层细节。在改动之前该模块的核心入口方法只接受普通字符串路径而现代 Python 生态中pathlib.Path已成为文件路径的标准表示方式Python 3.6 起os.PathLike协议正式确立。NumPy 的numpy.loadtxt、numpy.save等高层函数早已支持Path对象参见 numpy/lib/tests/test_io.py 中的TestPathUsage测试而_datasource作为npyio底层的文件打开通道却一度成为例外。本次改进正是补齐了这一缺口。二、受影响的 API 清单根据变更说明原文以下 API 现在接受os.PathLike本地路径API位置说明DataSource.open(path, mode, encoding, newline)numpy/lib/_datasource.py打开本地文件或下载并打开远程 URLDataSource.exists(path)numpy/lib/_datasource.py依次检查本地文件、本地缓存、远程 URL 是否存在DataSource.abspath(path)numpy/lib/_datasource.py返回文件在 DataSource 目录中的绝对路径Repository.open / exists / abspathnumpy/lib/_datasource.py上述方法在Repository中的对应实现先拼 baseurl 再委托给DataSource模块级open(path, mode, destpath, encoding, newline)numpy/lib/_datasource.py便捷函数内部实例化DataSource并调用其open注意DataSource与Repository的构造函数参数destpath、Repository的baseurl参数同样在文档签名中标注为 str or path-like见 DataSource.init与 Repository.init因此你可以直接用Path对象初始化它们。三、底层实现机制os.fspath()统一收敛源码层面的实现非常简洁且统一所有公开入口在处理路径时首先调用os.fspath(path)把PathLike对象规范化为字符串再走原有的字符串路径逻辑。以三个核心方法为例# DataSource.open 的入口 path os.fspath(path) # DataSource.exists 的入口 path os.fspath(path) # DataSource.abspath 的入口 path os.fspath(path)os.fspath()是 Python 3.6 引入的标准函数对于str与bytes直接原样返回对于实现了__fspath__()协议的对象典型如pathlib.Path返回其字符串表示否则抛出TypeError。因此这次改动实际上是把字符串专享的 API 收敛成了一切遵循os.PathLike协议的对象。模块级便捷函数open同样遵守该协议numpy/lib/_datasource.pypath os.fspath(path) ds DataSource(destpath) return ds.open(path, mode, encodingencoding, newlinenewline)Repository则通过_fullpath在拼接baseurl时先做os.fspathnumpy/lib/_datasource.py随后把完整路径委托给父类DataSource的对应方法因此Repository的所有入口同样自动获得了PathLike支持。从源码结构可以推断os.fspath被统一放在方法入口处意味着所有内部路径处理逻辑压缩扩展名探测、URL 解析、缓存定位等无需改动即可天然兼容Path对象这也是该改动保持低侵入、低风险的关键。四、测试佐证测试用例如何验证PathLike支持该改动并非孤立的文档声明numpy/lib/tests/test__datasource.py 中为每个 API 都补充了对应的PathFile测试形成完整闭环class TestDataSourceOpen: def test_PathFile(self, tmp_path): ds datasource.DataSource(tmp_path) local_file Path(valid_textfile(tmp_path)) with ds.open(local_file) as fh: assert_(fh) class TestDataSourceExists: def test_PathFile(self, tmp_path): ds datasource.DataSource(tmp_path) tmpfile Path(valid_textfile(tmp_path)) assert_(ds.exists(tmpfile)) missing tmp_path / missing.txt assert_equal(ds.exists(missing), False) class TestDataSourceAbspath: def test_PathFile(self, tmp_path): ds datasource.DataSource(tmp_path) tmpfile valid_textfile(tmp_path) assert_equal(tmpfile, ds.abspath(Path(tmpfile)))Repository一侧的覆盖同样完整TestRepositoryAbspath.test_PathFile验证repos.abspath(Path(tmpfilename))TestRepositoryExists.test_PathFile验证repos.exists(Path(tmpfilename))为 True、不存在的Path(missing.txt)为 FalseTestRepositoryOpen.test_PathFile验证repos.open(Path(tmpfilename))能正常返回文件对象TestOpenFunc.test_PathFile验证模块级datasource.open(local_file, destpathtmp_path)接受Path对象。这些测试同时验证了Path对象在只传文件名相对路径场景下的行为——测试中Path包装的是文件全路径但也覆盖了tmpfilename这种仅文件名的情况确保os.fspath后原有查找逻辑含destpath拼接不受影响。五、实战示例用pathlib.Path操作数据文件5.1 本地文件读写import pathlib from numpy.lib import npyio # 或直接使用 np.lib.npyio.DataSource / np.lib._datasource ds npyio.DataSource(pathlib.Path(/home/user/data)) local_path pathlib.Path(/home/user/data/sample.txt) # open返回普通文件对象可配合 with 使用 with ds.open(local_path) as fh: content fh.read() # exists本地文件是否存在 print(ds.exists(local_path)) # True print(ds.exists(pathlib.Path(/no/such/file.txt))) # False # abspath返回 DataSource 目录内的绝对路径 print(ds.abspath(local_path))5.2 与压缩文件协同DataSource打开文件时支持透明解压_FileOpeners会按扩展名自动选择gzip.open、bz2.open、lzma.open支持.gz、.bz2、.xz、.lzma无扩展名则使用内置open参见 numpy/lib/_datasource.py。现在这些路径也可以直接传Path对象import pathlib import gzip from numpy.lib import npyio # 构造一个 gzip 压缩文件 p pathlib.Path(/tmp/foobar.txt.gz) with gzip.open(p, w) as fp: fp.write(bthree is the magic number) ds npyio.DataSource(pathlib.Path(/tmp)) with ds.open(p) as fh: # Path 对象透明解压 print(fh.readline()) # bthree is the magic number5.3 远程 URL 与RepositoryPathLike支持同样适用于远程场景。DataSource遇到带 scheme 的 URL如http://、ftp://时会自动下载并缓存到destpath下然后返回本地缓存的文件对象ds npyio.DataSource(/home/user/cache) fp ds.open(http://www.example.com/data.txt) # 自动下载并缓存 fp.read() fp.close() print(ds.abspath(http://www.example.com/data.txt)) # /home/user/cache/www.example.com/data.txt而Repository适用于多个文件共享一个 baseurl/基础目录的场景初始化参数同样接受Pathfrom numpy.lib import npyio repos npyio.Repository(pathlib.Path(/home/user/data/dir/)) for filename in [a.csv, b.csv, c.csv]: with repos.open(filename) as fp: # 自动拼接 baseurl ...提示_datasource模块同时被 NumPy 的文件 IO 高层函数复用例如 numpy/lib/_npyio_impl.py 中的np.lib._datasource.open(fname, rt, encodingencoding)。因此本次PathLike支持也间接惠及loadtxt、savetxt、genfromtxt等函数的文件打开路径。六、注意事项与边界URL 必须带 schemeDataSource判断远程地址依赖urlparse解析出的 scheme 与 netloc见 _isurl。ds.exists(www.google.com/index.html)会返回False而ds.exists(http://www.google.com/index.html)才返回True。URL 不可写open检测到写模式mode 含w或且路径是 URL 时会抛出ValueError(URLs are not writeable)numpy/lib/_datasource.py。文件不存在会抛FileNotFoundErroropen在_findfile找不到任何候选含压缩变体时抛出FileNotFoundError(f{path} not found.)。临时目录生命周期当destpathNone时DataSource会通过tempfile.mkdtemp()创建临时目录并在对象被回收__del__时递归删除numpy/lib/_datasource.py。路径沙箱abspath会对传入路径做归一化与净化处理_sanitize_relative_path确保最终路径不会逃逸出destpath测试用例test_sandboxing专门覆盖了/etc/shadow、../../shadow等恶意输入numpy/lib/tests/test__datasource.py。七、总结DataSource/Repository的PathLike支持是一次小而关键的 API 一致性改进通过在每个入口统一调用os.fspath()让 NumPy 底层的数据文件抽象与现代 Python 的pathlib生态无缝衔接。从变更说明31906.improvement.rst到实现numpy/lib/_datasource.py再到测试numpy/lib/tests/test__datasource.py形成了完整的文档—实现—验证闭环。对于日常使用 NumPy 的开发者这意味着无论数据文件在本地、在远程服务器、还是压缩打包你都可以放心地把pathlib.Path对象直接传给DataSource、Repository及其open/exists/abspath方法再也不用为先转成字符串而编写多余的类型转换代码。赞分享科学计算数据分析【免费下载链接】numpyThe fundamental package for scientific computing with Python.项目地址https://gitcode.com/gh_mirrors/nu/numpy点击查看免费下载相关推荐全面解析PaddleSpeech对PaddlePaddle新版本的支持进展全面解析PaddleSpeech对PaddlePaddle新版本的支持进展 你还在为语音项目升级框架版本发愁一文带你掌握PaddleSpeech对Paddle人工智能语音音频创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考