pathlib.path 除了字符串和路径之外,允许其他类型的连接

pathlib.path allowing other types for joining apart from string and Path

如何更改 pathlib.Path._parse_args,以便我不仅可以使用其他类型(如 LocalPath)作为 Path 的参数,还可以使用其他类型作为 [=15] 的参数=] 基于加入等.?

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

tmplib 来自 py._path.localLocalPath,其他人自动转换为他们的 str() 表示?

我尝试了这个 () 问题中所示的子类化和猴子修补,但这没有用。

Path 看起来很抗拒扩展。

pathlib(对于 Python 版本 < 3.4 的 pathlib2)主要由四个 类 直接与路径 PathPosixPathWindowsPathPurePathpathlib2 中的 BasePath)。如果您将其中的每一个子类化并按以下方式复制和调整 Path.__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

您将拥有一个已经理解 int 并可用于执行以下操作的 Path

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

(您需要为版本 < 3.4 安装软件包 pathlib2 才能在这些版本上运行)。

上面的Path在Python3.6中可以作为open(p)使用。

适配 _parse_args 自动支持 / (__truediv__) 以及 joinpath()relative_to() 等方法

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

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)