4

我该如何更改pathlib.Path._parse_args,以便我不仅可以将其他类型(如 LocalPath)作为参数,Path还可以使用其他类型作为/基于连接的参数等。

from pathlib import Path
Path(tmplib) / 25 / True

使用from ,其他人自动转换为他们的tmplib表示?LocalPathpy._path.localstr()

我尝试了子类化和猴子修补,如这个(pathlib Path 和 py.test LocalPath)问题所示,但没有奏效。

Path看起来很抗拉。

4

2 回答 2

1

pathlibpathlib2对于 Python 版本 < 3.4)主要由四个与路径 、和Path( PosixPathin )直接相关的类组成。如果您将其中的每一个子类化并以下列方式复制和调整代码:WindowsPathPurePathBasePathpathlib2Path.__new__()PurePath._parse_args()

import os
import sys
if sys.version_info < (3, 4):
    import pathlib2 as pathlib
else:
    import pathlib


class PurePath(pathlib.Path):
    __slots__ = ()
    types_to_stringify = [int]

    @classmethod
    def _parse_args(cls, args):
        # This is useful when you don't want to create an instance, just
        # canonicalize some constructor arguments.
        parts = []
        for a in args:
            if isinstance(a, pathlib.PurePath):
                parts += a._parts
            elif sys.version_info < (3,) and isinstance(a, basestring):
                # Force-cast str subclasses to str (issue #21127)
                parts.append(str(a))
            elif sys.version_info >= (3, 4) and isinstance(a, str):
                # Force-cast str subclasses to str (issue #21127)
                parts.append(str(a))
            elif isinstance(a, tuple(PurePath.types_to_stringify)):
                parts.append(str(a))
            else:
                try:
                    parts.append(a)
                except:
                    raise TypeError(
                        "argument should be a path or str object, not %r"
                        % type(a))
        return cls._flavour.parse_parts(parts)


class WindowsPath(PurePath, pathlib.PureWindowsPath):
    __slots__ = ()


class PosixPath(PurePath, pathlib.PurePosixPath):
    __slots__ = ()


class Path(pathlib.Path):
    __slots__ = ()

    def __new__(cls, *args, **kwargs):
        if cls is Path:
            cls = WindowsPath if os.name == 'nt' else PosixPath
        self = cls._from_parts(args, init=False)
        if not self._flavour.is_supported:
            raise NotImplementedError("cannot instantiate %r on your system"
                                      % (cls.__name__,))
        self._init()
        return self

您将拥有一个Path已经理解int并且可以用来做的事情:

from py._path.local import LocalPath

# extend the types to be converted to string on the fly
PurePath.types_to_stringify.extend([LocalPath, bool])

tmpdir = LocalPath('/var/tmp/abc')

p = Path(tmpdir) / 14 / False / 'testfile.yaml'
print(p)

要得到:

/var/tmp/abc/14/False/testfile.yaml

(您需要安装pathlib2版本 < 3.4 的软件包才能使用这些软件包)。

以上Path可以open(p)在 Python 3.6 中使用。

Adapting为您提供对( ) 以及诸如 等方法的_parse_args自动支持。/__truediv__joinpath()relative_to()

于 2016-11-24T20:08:39.377 回答
1

如果你想保持平台独立的魔力,你可以这样做:

from py._path.local import LocalPath
import os
import pathlib


class Path(pathlib.Path):

    def __new__(cls, *args, **kwargs):
        if cls is Path:
            cls = WindowsPath if os.name == 'nt' else PosixPath
        return cls._from_parts(map(str, args))

    def __truediv__(self, other):
        return super().__truediv__(str(other))

class WindowsPath(Path, pathlib.WindowsPath):
    pass
class PosixPath(Path, pathlib.PosixPath):
    pass

p = Path(LocalPath())
print(p / 25 / True)

或者如果可以特定于平台,就这样:

from py._path.local import LocalPath
import pathlib


class Path(pathlib.PosixPath):

    def __new__(cls, *args, **kwargs):
        return cls._from_parts(map(str, args))

    def __truediv__(self, other):
        return super().__truediv__(str(other))


p = Path(LocalPath())
print(p / 25 / True)
于 2016-11-24T20:11:25.657 回答