相较于标准pathlib模块和pathlib2包的改进
项目描述
ruamel.std.pathlib
包ruamel.std.pathlib是一个用于扩展Python标准pathlib
模块的即插即用替代品。
您可以简单地替换
from pathlib import PosixPath, Path
为
from ruamel.std.pathlib import PosixPath, Path
从0.8.0版本开始,ruamel.std.pathlib
不再支持Python 2
额外的路径功能
- 将Path上的
remove
别名设置为unlink
- 向Path添加来自shutil的
copy()
和rmtree()
- 向path添加
hash()
,返回文件内容的hashlib.new()
值(默认为'sha224',可以提供其他算法作为参数:print(p.hash('md5').hexdigest())
) - 向一个(目录)Path添加
pushd()
和popd()
,这保留了一个可能包含多个条目的堆栈。 - 向Path添加
rmtree()
,在Path上调用shutil.rmtree()
- 向一个(目录)Path添加
chdir()
- 向Path添加
stabilise()
,等待它不再改变,可以设置duration
(默认5秒),recheck
(默认0.2秒),以及如果尚未稳定,则显示一次的消息。
blake3
当你安装了blake3
(这不是此包的依赖项)并执行import ruamel.std.pathlib.blake3
时,你还可以在Path
实例上使用该方法。
json
当你执行import ruamel.std.pathlib.json
时,这将按顺序加载orjson/ujson/json到一个Path,这样你就可以执行data = path.json.load()
和path.json.dump(data)
msgpack
当你安装了ruamel.ext.msgpack
并执行import ruamel.std.pathlib.msgpack
并且有一个Path
实例path
时,你可以执行data = path.msgpack.load()
和path.msgpack.dump(data)
tar
当您已安装 zstandard
并执行 import ruamel.std.pathlib.tar
,并且拥有一个 Path
实例 path
时,您可以对 .tar.zst
文件执行 with path.tar.open()
操作,实现内存中的解压缩。
转换助手
如果您刚开始使用标准的 pathlib 库,一次性更改所有内容会很麻烦,同时还需要将所有调用 os.path.join
、os.rename
、os.path.dirname
的参数封装在 str()
中。
通过创建一个名为 pl
的 PathLibConversionHelper
实例,您可以将 os.path.join()
更改为 pl.path.join()
等,然后开始传递 Path 实例而不是字符串。
PathLibConversionHelper
目前支持以下对 os
的替换:
: os.path
、shutil
和内置函数
.chdir() replaces: os.chdir()
.copy() replaces: shutil.copy()
.glob() replaces: glob.glob()
.listdir() replaces: os.listdir()
.makedirs() replaces: os.makedirs()
.mkstemp() replaces: tempfile.mkstemp()
.open() replaces: built-in open()
.path.basename() replaces: os.path.basename()
.path.dirname() replaces: os.path.dirname()
.path.exists() replaces: os.path.exists()
.path.expanduser() replaces: os.path.expanduser()
.path.getmtime() replaces: os.path.getmtime()
.path.isdir() replaces: os.path.isdir()
.path.join() replaces: os.path.join()
.path.splitext() replaces: os.path.splitext()
.remove() replaces: os.remove()
.rename() replaces: os.rename()
.rmdir() replaces: os.rmdir()
.rmtree() replaces: shutil.rmtree()
.walk() replaces: os.walk()
在创建 PathLibConversionHelper()
实例时,您可以提供检查级别。
- 如果检查值非零,所有调用都将被记录,并且调用可以通过
pl.dump(stream, show_all=False)
输出,例如在程序结束时。这将包括未使用 Path 的调用次数(以及如果show_all=True
,仅使用 Path 的调用次数)。 - 如果检查值大于 1,则立即输出第一次使用。
如果您开始使用以下代码
# coding: utf-8
import os
import glob
import tempfile
import shutil
import random
class TempDir(object):
"""self removing (unless keep=True) temporary directory"""
def __init__(self, keep=False, basedir=None, prefix=None):
self._keep = keep
# mkdtemp creates with permissions rwx------
kw = dict(dir=basedir)
if prefix is not None:
kw['prefix'] = prefix
# mkdtemp doesn't do the right thing if None is passed in
# as it has prefix=template in definition
self._tmpdir = tempfile.mkdtemp(**kw)
def remove(self):
shutil.rmtree(self._tmpdir)
def chdir(self):
os.chdir(self._tmpdir)
def tempfilename(self, extension=''):
fd, name = tempfile.mkstemp(suffix=extension, dir=self._tmpdir)
os.close(fd)
return name
def tempfilename2(self, extension=''):
while True:
name = os.path.join(
self._tmpdir,
'%08d' % random.randint(0, 100000) + extension
)
if not os.path.exists(name):
break
return name
@property
def directory(self):
return self._tmpdir
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if not self._keep:
self.remove()
def main():
"""contrived example using TempDir"""
org_dir = os.getcwd()
with TempDir() as td:
for n in range(3):
t1 = td.tempfilename(extension='.sample')
with open(t1, 'w') as fp:
fp.write('content\n')
t2 = td.tempfilename2(extension='.sample2')
with open(t2, 'w') as fp:
fp.write('content\n')
os.chdir(td.directory)
count = 0
for file_name in glob.glob('*.samp*'):
full_name = os.path.join(os.getcwd(), file_name) # noqa
# print(full_name)
count += 1
os.chdir('/tmp') # not using Path
os.chdir(org_dir)
print('{} files found in temporary directory'.format(count))
main()
您将得到
4 files found in temporary directory
当您开始将 TempDir()
更改为将实际目录作为 Path 存储时,事情会立即开始出错
# coding: utf-8
import os
import glob
import tempfile
import shutil
import random
from ruamel.std.pathlib import Path # added
class TempDir(object):
"""self removing (unless keep=True) temporary directory"""
def __init__(self, keep=False, basedir=None, prefix=None):
self._keep = keep
# mkdtemp creates with permissions rwx------
kw = dict(dir=basedir)
if prefix is not None:
kw['prefix'] = prefix
# mkdtemp doesn't do the right thing if None is passed in
# as it has prefix=template in definition
self._tmpdir = Path(tempfile.mkdtemp(**kw)) # changed
def remove(self):
shutil.rmtree(self._tmpdir)
def chdir(self):
os.chdir(self._tmpdir)
def tempfilename(self, extension=''):
fd, name = tempfile.mkstemp(suffix=extension, dir=self._tmpdir)
os.close(fd)
return name
def tempfilename2(self, extension=''):
while True:
name = os.path.join(
self._tmpdir,
'%08d' % random.randint(0, 100000) + extension
)
if not os.path.exists(name):
break
return name
@property
def directory(self):
return self._tmpdir
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if not self._keep:
self.remove()
def main():
"""contrived example using TempDir"""
org_dir = os.getcwd()
with TempDir() as td:
for n in range(3):
t1 = td.tempfilename(extension='.sample')
with open(t1, 'w') as fp:
fp.write('content\n')
t2 = td.tempfilename2(extension='.sample2')
with open(t2, 'w') as fp:
fp.write('content\n')
os.chdir(td.directory)
count = 0
for file_name in glob.glob('*.samp*'):
full_name = os.path.join(os.getcwd(), file_name) # noqa
# print(full_name)
count += 1
os.chdir('/tmp') # not using Path
os.chdir(org_dir)
print('{} files found in temporary directory'.format(count))
main()
有一些错误
Traceback (most recent call last):
File "_example/stage1.py", line 80, in <module>
main()
File "_example/stage1.py", line 77, in main
os.chdir(org_dir)
File "_example/stage1.py", line 56, in __exit__
self.remove()
File "_example/stage1.py", line 27, in remove
shutil.rmtree(self._tmpdir)
File "/opt/python/2.7.13/lib/python2.7/shutil.py", line 228, in rmtree
if os.path.islink(path):
File "/home/venv/dev/lib/python2.7/posixpath.py", line 135, in islink
st = os.lstat(path)
TypeError: coercing to Unicode: need string or buffer, PosixPath found
而不是一次性更改程序中的所有使用,并希望它再次工作,您替换了标准模块中的例程
# coding: utf-8
import os
import glob
import tempfile
import shutil # noqa
import random
from ruamel.std.pathlib import Path, PathLibConversionHelper # changed
pl = PathLibConversionHelper() # added
class TempDir(object):
"""self removing (unless keep=True) temporary directory"""
def __init__(self, keep=False, basedir=None, prefix=None):
self._keep = keep
# mkdtemp creates with permissions rwx------
kw = dict(dir=basedir)
if prefix is not None:
kw['prefix'] = prefix
# mkdtemp doesn't do the right thing if None is passed in
# as it has prefix=template in definition
self._tmpdir = Path(tempfile.mkdtemp(**kw))
def remove(self):
pl.rmtree(self._tmpdir)
def chdir(self):
os.chdir(self._tmpdir)
def tempfilename(self, extension=''):
fd, name = pl.mkstemp(suffix=extension, dir=self._tmpdir) # changed
os.close(fd)
return name
def tempfilename2(self, extension=''):
while True:
name = pl.path.join(
self._tmpdir,
'%08d' % random.randint(0, 100000) + extension
)
if not pl.path.exists(name): # changed
break
return name
@property
def directory(self):
return self._tmpdir
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if not self._keep:
self.remove()
def main():
"""contrived example using TempDir"""
org_dir = os.getcwd()
with TempDir() as td:
for n in range(3):
t1 = td.tempfilename(extension='.sample')
with open(t1, 'w') as fp:
fp.write('content\n')
t2 = td.tempfilename2(extension='.sample2')
with pl.open(t2, 'w') as fp:
c = 'content\n' # added
if not isinstance(fp, file): # added
c = unicode(c) # added
fp.write(c) # changed
pl.chdir(td.directory)
count = 0
for file_name in glob.glob('*.samp*'):
full_name = pl.path.join(os.getcwd(), file_name) # noqa # changed
# print(full_name)
count += 1
pl.chdir('/tmp') # not using Path
pl.chdir(org_dir) # changed
print('{} files found in temporary directory'.format(count))
main()
(再次)
4 files found in temporary directory
只需将 self._tempdir
的创建改回原始版本
self._tmpdir = tempfile.mkdtemp(**kw)
输出保持不变
4 files found in temporary directory
如果您现在将 pl
的创建改为
pl = PathLibConversionHelper(check=2)
您将得到以下输出
update .mkstemp to use Path.mkstemp() [_example/stage3.py:34 / Path (True,)]
update .path.join to use "/" [_example/stage3.py:42 / Path (True, False)]
update .exists to use Path.exists() [_example/stage3.py:44 / Path (True,)]
update .open to use Path.open() [_example/stage3.py:69 / Path (True,)]
update .chdir to use Path.chdir() or os.chdir(str(Path)) [_example/stage3.py:74 / Path (True,)]
update .path.join to use "/" [_example/stage3.py:77 / Path (False, False)]
update .chdir to use Path.chdir() or os.chdir(str(Path)) [_example/stage3.py:80 / Path (False,)]
update .chdir to use Path.chdir() or os.chdir(str(Path)) [_example/stage3.py:81 / Path (False,)]
update .rmtree to use Path.rmtree() or shutil.rmtree(str(Path)) [_example/stage3.py:28 / Path (True,)]
4 files found in temporary directory
如果您使用 check=1
并在最后执行 pl.dump()
,您将得到
4 files found in temporary directory
update .path.join to use "/" [_example/stage4.py:42 / 1 / Path (True, False)]
update .chdir to use Path.chdir() or os.chdir(str(Path)) [_example/stage4.py:81 / 1 / Path (False,)]
update .path.join to use "/" [_example/stage4.py:77 / 4 / Path (False, False)]
update .chdir to use Path.chdir() or os.chdir(str(Path)) [_example/stage4.py:80 / 1 / Path (False,)]
显示您仍然使用的基于字符串的路径/文件名。
消息部分 file_name.py: 123 / 2 / Path (True, False)
表示在 file_name.py
中的第 123 行有两次调用,并且它们调用时第一个参数是 Path,第二个不是 Path(当将 os.path.join()
替换为 Path 的 /
连接运算符时,这是一个很好的起点,对于其他情况,您可能还需要将第二个参数转换为 Path 实例)。
扩展 PathLibConversionHelper
如果 PathLibConversionHelper
还没有包含某个特定函数,您可以轻松地继承它并添加自己的。
from ruamel.std.pathlib import Path, PathLibConversionHelper
class MyPLCH(PathLibConversionHelper):
# an example, ruamel.std.pathlib already adds mkstemp
def mkstemp(self, suffix="", prefix=None, dir=None, text=False):
import tempfile
# would be much better if prefix defaults to built-in value (int, None, string)
if prefix is None:
prefix = tempfile.template
self.__add_usage(dir, 'update .mkstemp to use Path.mkstemp()')
if isinstance(dir, Path):
dir = str(dir)
return tempfile.mkstemp(suffix, prefix, dir, text)
pl = MyPLCH(check=1)
self.add_usage()
的第一个参数用于确定是否使用了 Path。这应该是一个包含所有相关变量(可以是 Path
实例也可以不是)的列表。如果列表只有一个元素,则不需要作为列表传入(如示例所示)。第二个参数应该是一个字符串,其中包含有关进一步消除对 .mkstemp()
调用的帮助信息。
项目详情
下载文件
下载您平台的文件。如果您不确定选择哪个,请了解更多关于 安装包 的信息。
源代码分发
构建的发行版
ruamel.std.pathlib-0.13.0.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 1387e81655999851241b07f68569901ba4d502804094cde3c327b849ae702bb8 |
|
MD5 | 1a92e5eb5577815ad08dcf71d66aa1c0 |
|
BLAKE2b-256 | 1a1df7a7fdf3765f5b05b595c9ac6e4ee1fffc990512b475f6a71abd1da341b4 |
ruamel.std.pathlib-0.13.0-py3-none-any.whl 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 3af398d4f7294ca449890a2b33f8d0068471c2d3888da3b3e37fc025ea137229 |
|
MD5 | ed67a133d08eb109df498ca5c8d834e0 |
|
BLAKE2b-256 | c935bce6e350012133d93075e14a604efd02c09b78788f8042b070192ded7a6d |