简单简洁的路径遍历和文件系统访问库。
项目描述
注意: 这处于非常早期的测试版。
简单简洁的路径遍历和文件系统访问库。这个库与其他路径操作库略有不同
路径是字符串的子类。您可以在任何使用字符串的地方使用它们。
几乎所有来自os.path的内容都可以作为同名的属性使用,除了
os.path.relpath是一个方法
os.path.getsize变成了名为size的属性
os.path.getatime变成了名为atime的属性
os.path.getctime变成了名为ctime的属性
os.path.getmtime变成了名为mtime的属性
os.path.split变成了名为splitpath的方法,因为split已经是字符串方法了
os.path.join变成了名为joinpath的方法,因为join已经是字符串方法了
os.path.commonprefix 未实现
os.path.basename 变成名为 name 的 属性
os.path.dirname 变成名为 dir 的 属性
os.listdir 变成名为 list 的 属性
os.walk 变成名为 tree 的 属性
调用 Path 对象会调用路径上的 open()。接受 open 可以接受的任何参数(当然不包括文件名)。
透明支持 .zip 文件中的文件。
基本上,它是为了极致的简洁而设计的。它采用了 Unipath 的 str 子类化方法,并且具有无缝的 zip 支持(类似于 Twisted 的 ZipPath)。
用法
入门指南
>>> import pth
>>> pth # the module is a function!
<function pth at ...>
>>> p = pth("a.txt")
>>> p
<Path 'a.txt'>
>>> p
<Path 'a.txt'>
API
>>> p = pth('tests')
>>> p
<Path 'tests'>
连接路径
>>> p/"a"/"b"/"c"/"d" <Path 'tests/a/b/c/d'> >>> p/"/root" <Path '/root'>
属性
>>> p.abspath
<Path '/.../tests'>
>>> p2 = p/'b.txt'
>>> p2
<Path 'tests/b.txt'>
>>> p.exists
True
>>> p2.isfile
True
>>> p2()
<...'tests/b.txt'...mode...'r'...>
>>> pth('bogus-doesnt-exist')()
Traceback (most recent call last):
...
pth.PathMustBeFile: [Errno 2] No such file or directory: ...
遍历子项,包括 .zip 文件中的文件
>>> for i in sorted([i for i in p.tree]): print(i)
tests/a
tests/a/a.txt
tests/b.txt
tests/test.zip
tests/test.zip/1
tests/test.zip/1/1.txt
tests/test.zip/B.TXT
tests/test.zip/a.txt
>>> for i in sorted([i for i in p.files]): print(i)
tests/b.txt
>>> for i in sorted([i for i in p.dirs]): print(i)
tests/a
tests/test.zip
>>> for i in sorted([i for i in p.list]): print(i)
tests/a
tests/b.txt
tests/test.zip
>>> list(pth('bogus-doesnt-exist').tree)
Traceback (most recent call last):
...
pth.PathMustBeDirectory: <Path 'bogus-doesnt-exist'> is not a directory nor a zip !
尝试访问不存在的属性
>>> p.bogus Traceback (most recent call last): ... AttributeError: 'Path' object has no attribute 'bogus'
自动包装 zip 文件
>>> p/'test.zip' <ZipPath 'tests/test.zip' / ''>
其他属性
>>> p.abspath
<Path '/.../tests'>
>>> p.abs
<Path '/.../tests'>
>>> p.basename
<Path 'tests'>
>>> p.abs.basename
<Path 'tests'>
>>> p.name
<Path 'tests'>
>>> p.dirname
<Path ''>
>>> p.dir
<Path ''>
>>> p.exists
True
>>> pth('~root').expanduser
<Path '/root'>
>>> pth('~/stuff').expanduser
<Path '/home/.../stuff'>
>>> p.expandvars
<Path 'tests'>
>>> type(p.atime)
<... 'float'>
>>> type(p.ctime)
<... 'float'>
>>> type(p.size)
<... 'int'>
>>> p.isabs
False
>>> p.abs.isabs
True
>>> p.isdir
True
>>> p.isfile
False
>>> p.islink
False
>>> p.ismount
False
>>> p.lexists
True
>>> p.normcase
<Path 'tests'>
>>> p.normpath
<Path 'tests'>
>>> p.realpath
<Path '/.../tests'>
>>> p.splitpath
(<Path ''>, <Path 'tests'>)
>>> pth('a/b/c/d').splitpath
(<Path 'a/b/c'>, <Path 'd'>)
>>> pth('a/b/c/d').parts
[<Path 'a'>, <Path 'b'>, <Path 'c'>, <Path 'd'>]
>>> pth('/a/b/c/d').parts
[<Path '/'>, <Path 'a'>, <Path 'b'>, <Path 'c'>, <Path 'd'>]
>>> pth(*pth('/a/b/c/d').parts)
<Path '/a/b/c/d'>
>>> p.splitdrive
('', <Path 'tests'>)
>>> p.drive
''
>>> [i for i in (p/'xxx').tree]
Traceback (most recent call last):
...
pth.PathMustBeDirectory: <Path 'tests/xxx'> is not a directory nor a zip !
>>> (p/'xxx').isfile
False
>>> (p/'xxx')()
Traceback (most recent call last):
...
pth.PathMustBeFile: ... 2...
>>> p()
Traceback (most recent call last):
...
pth.PathMustBeFile: <Path 'tests'> is not a file !
>>> pth('a.txt').splitext
(<Path 'a'>, '.txt')
>>> pth('a.txt').ext
'.txt'
Zip 相关内容
>>> z = pth('tests/test.zip')
>>> z
<ZipPath 'tests/test.zip' / ''>
>>> z.abspath
<ZipPath '/.../tests/test.zip' / ''>
>>> z.abs
<ZipPath '/.../tests/test.zip' / ''>
>>> z.basename # transforms in normal path cauze zip is not accessible in current dir
<Path 'test.zip'>
>>> z.abs.basename # transforms in normal path cauze zip is not accessible in current dir
<Path 'test.zip'>
>>> import os
>>> os.chdir('tests')
>>> z.basename
<ZipPath 'test.zip' / ''>
>>> z.name
<ZipPath 'test.zip' / ''>
>>> os.chdir('..')
>>> z.dirname
<Path 'tests'>
>>> z.abs.dirname
<Path '/.../tests'>
>>> z.dir
<Path 'tests'>
>>> z.exists
True
>>> pth('~root').expanduser
<Path '/root'>
>>> pth('~/stuff').expanduser
<Path '/home/.../stuff'>
>>> z.expandvars
<ZipPath 'tests/test.zip' / ''>
>>> type(z.atime)
Traceback (most recent call last):
...
AttributeError: Not available here.
>>> type(z.ctime)
<... 'float'>
>>> type(z.size)
<... 'int'>
>>> z.isabs
False
>>> z.abs.isabs
True
>>> z.isdir
True
>>> z.isfile
False
>>> z.islink
False
>>> z.ismount
False
>>> z.lexists
Traceback (most recent call last):
...
AttributeError: Not available here.
>>> for i in z.tree: print((str(i), repr(i)))
('tests/test.zip/1',...... "<ZipPath 'tests/test.zip' / '1/'>")
('tests/test.zip/1/1.txt', "<ZipPath 'tests/test.zip' / '1/1.txt'>")
('tests/test.zip/B.TXT',..."<ZipPath 'tests/test.zip' / 'B.TXT'>")
('tests/test.zip/a.txt',..."<ZipPath 'tests/test.zip' / 'a.txt'>")
>>> for i in z.files: print((str(i), repr(i)))
('tests/test.zip/B.TXT',..."<ZipPath 'tests/test.zip' / 'B.TXT'>")
('tests/test.zip/a.txt',..."<ZipPath 'tests/test.zip' / 'a.txt'>")
>>> for i in z.dirs: print((str(i), repr(i)))
('tests/test.zip/1',...... "<ZipPath 'tests/test.zip' / '1/'>")
>>> for i in z.list: print((str(i), repr(i)))
('tests/test.zip/1',...... "<ZipPath 'tests/test.zip' / '1/'>")
('tests/test.zip/B.TXT',..."<ZipPath 'tests/test.zip' / 'B.TXT'>")
('tests/test.zip/a.txt',..."<ZipPath 'tests/test.zip' / 'a.txt'>")
>>> (z/'B.TXT')
<ZipPath 'tests/test.zip' / 'B.TXT'>
>>> str(z/'B.TXT')
'tests/test.zip/B.TXT'
>>> (z/'B.TXT').dirname
<ZipPath 'tests/test.zip' / ''>
>>> (z/'B.TXT').rel(z)
<Path 'B.TXT'>
>>> z.rel(z/'B.TXT')
<Path '..'>
>>> (z/'B.TXT').exists
True
>>> (z/'B.TXT').normcase
<ZipPath 'tests/test.zip' / 'B.TXT'>
>>> (z/'B.TXT').normpath
<ZipPath 'tests/test.zip' / 'B.TXT'>
>>> (z/'B.TXT').name
<Path 'B.TXT'>
>>> (z/'B.TXT').name
<Path 'B.TXT'>
>>> z.normcase
<ZipPath 'tests/test.zip' / ''>
>>> z.normpath
<ZipPath 'tests/test.zip' / ''>
>>> z.realpath
<ZipPath '/.../tests/test.zip' / ''>
>>> z.splitpath
(<Path 'tests'>, <Path 'test.zip'>)
>>> z.splitdrive
('', <ZipPath 'tests/test.zip' / ''>)
>>> z.drive
''
>>> pth('a.txt').splitext
(<Path 'a'>, '.txt')
>>> pth('a.txt').ext
'.txt'
在 .zip 文件中处理文件
>>> p = z/'B.TXT'
>>> p.abspath
<ZipPath '/.../tests/test.zip' / 'B.TXT'>
>>> p.abs
<ZipPath '/.../tests/test.zip' / 'B.TXT'>
>>> p.basename
<Path 'B.TXT'>
>>> p.abs.basename
<Path 'B.TXT'>
>>> p.name
<Path 'B.TXT'>
>>> p.dirname
<ZipPath 'tests/test.zip' / ''>
>>> p.dir
<ZipPath 'tests/test.zip' / ''>
>>> p.exists
True
>>> type(p.atime)
Traceback (most recent call last):
...
AttributeError: Not available here.
>>> type(p.ctime)
<... 'float'>
>>> type(p.size)
<... 'int'>
>>> p.isabs
False
>>> p.abs.isabs
True
>>> p.isdir
False
>>> p.isfile
True
>>> p.islink
False
>>> p.ismount
False
>>> p.lexists
Traceback (most recent call last):
...
AttributeError: Not available here.
>>> p.normcase
<ZipPath 'tests/test.zip' / 'B.TXT'>
>>> p.normpath
<ZipPath 'tests/test.zip' / 'B.TXT'>
>>> p.realpath
<ZipPath '/.../tests/test.zip' / 'B.TXT'>
>>> p.splitpath
(<ZipPath 'tests/test.zip' / ''>, <Path 'B.TXT'>)
>>> pth.ZipPath.from_string('tests/test.zip/1/1.txt')
<ZipPath 'tests/test.zip' / '1/1.txt'>
>>> p.splitdrive
('', <ZipPath 'tests/test.zip' / 'B.TXT'>)
>>> p.drive
''
>>> p.splitext
(<ZipPath 'tests/test.zip' / 'B'>, '.TXT')
>>> p.ext
'.TXT'
>>> p.joinpath('tete')
<ZipPath 'tests/test.zip' / 'B.TXT/tete'>
>>> p.joinpath('tete').exists
False
>>> p.joinpath('tete').isdir
False
>>> p.joinpath('tete').isfile
False
>>> p.joinpath('tete').ctime
Traceback (most recent call last):
...
pth.PathDoesNotExist: "There is no item named 'B.TXT/tete' in the archive"
>>> p.joinpath('tete').size
Traceback (most recent call last):
...
pth.PathDoesNotExist: "There is no item named 'B.TXT/tete' in the archive"
>>> p.relpath('tests')
<Path 'test.zip/B.TXT'>
>>> p.joinpath('tete')('rb')
Traceback (most recent call last):
...
pth.PathMustBeFile: <ZipPath 'tests/test.zip' / 'B.TXT/tete'> is not a file !
>>> p('r')
<zipfile.ZipExtFile ...>
>>> [i for i in p.tree]
Traceback (most recent call last):
...
pth.PathMustBeDirectory: <ZipPath 'tests/test.zip' / 'B.TXT'> is not a directory !
>>> z('rb')
Traceback (most recent call last):
...
pth.PathMustBeFile: <ZipPath 'tests/test.zip' / ''> is not a file !
遍历 zip 文件的内容
>>> [i for i in z.tree] [<ZipPath 'tests/test.zip' / '1/'>, <ZipPath 'tests/test.zip' / '1/1.txt'>, <ZipPath 'tests/test.zip' / 'B.TXT'>, <ZipPath 'tests/test.zip' / 'a.txt'>] >>> [i for i in z.files] [<ZipPath 'tests/test.zip' / 'B.TXT'>, <ZipPath 'tests/test.zip' / 'a.txt'>] >>> [i for i in z.dirs] [<ZipPath 'tests/test.zip' / '1/'>]
注意,在连接绝对路径时存在这种不一致性
>>> z/pth('/root')
<Path '/root'>
与
>>> z/'/root' <ZipPath 'tests/test.zip' / '/root'>
TODO:使其更美观。
>>> pth.ZipPath('tests', '', '')
<Path 'tests'>
>>> pth.ZipPath.from_string('/bogus/path/to/stuff/bla/bla/bla')
<Path '/bogus/path/to/stuff/bla/bla/bla'>
>>> pth.ZipPath.from_string('bogus')
<Path 'bogus'>
>>> pth.ZipPath.from_string('tests/test.zip/bogus/path/to/stuff/bla/bla/bla')
<ZipPath 'tests/test.zip' / 'bogus/path/to/stuff/bla/bla/bla'>
>>> pth.ZipPath.from_string('tests/1/bogus/path/to/stuff/bla/bla/bla')
<Path 'tests/1/bogus/path/to/stuff/bla/bla/bla'>
>>> pth.ZipPath.from_string('tests')
<Path 'tests'>
>>> pth.ZipPath.from_string('tests/bogus')
<Path 'tests/bogus'>
还有一个 临时路径
>>> t = pth.TempPath()
>>> t
<TempPath '/tmp/...'>
>>> with t:
... with (t/"booo.txt")('w+') as f:
... _ = f.write("test")
... print([i for i in t.tree])
[<Path '/tmp/.../booo.txt'>]
>>> t.exists
False
变更日志
0.1.0 (2014-06-10)
首次发布在 PyPI 上。
项目详情
下载文件
下载您平台上的文件。如果您不确定选择哪个,请了解更多关于 安装软件包 的信息。
源代码分发
构建分发
pth-0.3.0.tar.gz 的哈希值
| 算法 | 哈希摘要 | |
|---|---|---|
| SHA256 | 206e5f104d8f4949b66c6f418d30e585546ef8cdd08428a556ddc43f25c07cd4 |
|
| MD5 | 02e3cfe0e74f06292cf9729c4de30f78 |
|
| BLAKE2b-256 | 6f6831fda6cb2092373ce5ba460139b0ee37814411927e3a6f5e9847679b6ef7 |
pth-0.3.0-py2.py3-none-any.whl 的哈希值
| 算法 | 哈希摘要 | |
|---|---|---|
| SHA256 | 1c7f7b1456ec8a97ac2ea71b1f1ceb7d35fcdcd07c8845fda5585b8fb157aa97 |
|
| MD5 | 9c00d19f1ae7fa2c5c352b08b81d11b2 |
|
| BLAKE2b-256 | 880a0c01ca43eace546a12bc2fd2ab95588c1a87c3fec853d169ff57c1a60168 |