对标准pathlib模块和pathlib2包的改进

ruamel.std.pathlib的Python项目详细描述


package ruamel.std.pathlib是一个下拉列表 替换以扩展python标准的pathlib`模块。

您只需替换:

from pathlib import PosixPath, Path

使用:

from ruamel.std.pathlib import PosixPath, Path

对于较旧版本的python,它还用作依赖项检查。 从pypi安装pathlib2。你只需要 您的包依赖于ruamel.std.pathlibpathlib2 将在必要时安装。

额外路径功能

  • 路径上unlink的别名remove
  • copy()rmtree()从shutil添加到路径
  • hash()添加到path返回 文件内容(默认为“sha224”,其他算法如下 参数:print(p.hash('md5').hexdigest())

转换助手

如果开始使用标准的pathlib库,则 立即更改所有内容,并将所有参数更改为调用 os.path.joinos.renameos.path.dirname封装在str()

通过将PathLibConversionHelper的实例命名为pl,您可以更改 os.path.join()pl.path.join()等,然后开始传入路径 实例而不是字符串。

PathLibConversionHelper目前支持以下操作系统的替换

os.pathshuil和内置函数:

.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()实例。

  • 如果check为非零,则记录所有调用并调用 可以转储,例如在程序结束时 pl.dump(stream, show_all=False)这将包括 不使用path(以及唯一使用path)的调用数 如果show_all=True
  • 如果check大于1,则立即转储第一次使用。

如果您从以下代码开始:

# coding: utf-8

from __future__ import print_function

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()以存储 实际目录作为路径,会立即中断:

# coding: utf-8

from __future__ import print_function

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

from __future__ import print_function

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行有两个调用 第一个参数是路径,第二个不是路径(替换时 os.path.join()与路径的"/"连接运算符 作为一个好的起点,对于其他情况,您可能需要转换 路径实例的第二个参数)。

扩展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实例,也可能不是)。如果名单上只有 它不必作为列表传入(如 示例)。第二个参数应该是一个字符串,可以进一步帮助 取消对.mkstemp()的调用。

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java Cassandra复制因子大于节点数   java J2EE JTA事务回滚不适用于OSE Glassfish 4.0(Build 89)   java spring安全预认证用户登录   org的java类文件。反应流。从RxJava编译示例时未找到Publisher?   java在使用dataFormat作为POJO通过Camel调用Web服务时无法设置SOAP标头   Javafx类的java静态实例   java如何防止一个部件在关闭时覆盖另一个部件的位置   sql server无法从我的java代码连接到数据库   java在JList(Swing)中显示带有的ArrayList   从Java中的CXF服务获取WSAddressing数据   使用资产文件夹进行java简单json解析(本地)   java LDAPException未绑定的无效凭据   JavaJSFspring部署到weblogic   JAVA中字符数组中的特定元素排列?   如果脚本位于不同的目录中,则ant不会使用exec标记运行Javashell脚本