将pathlib用于s3路径

bea*_*rdc 5 python python-3.x pathlib

我想构建一些功能来在s3和本地文件系统之间移动文件,但是pathlib似乎吃掉了很多重复的斜杠,从而破坏了我的aws-cli功能:

from pathlib import Path
p = Path('s3://loc')
str(p)
=> 's3:/loc'
Run Code Online (Sandbox Code Playgroud)

有没有一种方法可以使用pathlib来处理s3路径?

kic*_*hik 6

您可以尝试将urllib.parsepathlib结合使用。

from urllib.parse import urlparse, urlunparse
from pathlib import PosixPath

s3_url = urlparse('s3://bucket/key')
s3_path = PosixPath(s3_url.path)
s3_path /= 'hello'
s3_new_url = urlunparse((s3_url.scheme, s3_url.netloc, s3_path.as_posix(), s3_url.params, s3_url.query, s3_url.fragment))
print(s3_new_url)
Run Code Online (Sandbox Code Playgroud)

这很麻烦,但这正是您要的。


Acu*_*nus 6

使用s3path

s3path软件包使使用 S3 路径的痛苦减轻了一些。它可以从PyPIconda- forge安装。将该S3Path类用于 S3 中的实际对象,否则使用PureS3Path不应实际访问 S3 的对象。

虽然metaperture上一个答案确实提到了这个包,但它没有包含 URI 语法。

另请注意,此软件包存在某些缺陷,这些缺陷已在其问题中报告。

>>> from s3path import PureS3Path

>>> PureS3Path.from_uri('s3://mybucket/foo/bar') / 'add/me'
PureS3Path('/mybucket/foo/bar/add/me')

>>> _.as_uri()
's3://mybucket/foo/bar/add/me'
Run Code Online (Sandbox Code Playgroud)

请注意与 的实例关系pathlib

>>> from pathlib import Path, PurePath
>>> from s3path import S3Path, PureS3Path

>>> isinstance(S3Path('/my-bucket/some/prefix'), Path)
True
>>> isinstance(PureS3Path('/my-bucket/some/prefix'), PurePath)
True
Run Code Online (Sandbox Code Playgroud)

使用 pathlib.Path

这是 kichik 仅使用pathlib. 不一定推荐这种方法。使用urllib.parse.

>>> from pathlib import Path

>>> orig_s3_path = 's3://mybucket/foo/bar'
>>> orig_path = Path(*Path(orig_s3_path).parts[1:])
>>> orig_path
PosixPath('mybucket/foo/bar')

>>> new_path = orig_path / 'add/me'
>>> new_s3_path = 's3://' + str(new_path)
>>> new_s3_path
's3://mybucket/foo/bar/add/me'
Run Code Online (Sandbox Code Playgroud)

使用 os.path.join

仅用于简单连接,怎么样os.path.join

>>> import os

>>> os.path.join('s3://mybucket/foo/bar', 'add/me')
's3://mybucket/foo/bar/add/me'
>>> os.path.join('s3://mybucket/foo/bar/', 'add/me')
's3://mybucket/foo/bar/add/me'
Run Code Online (Sandbox Code Playgroud)

os.path.normpath 但是不能天真地使用:

>>> os.path.normpath('s3://mybucket/foo/bar')  # Converts 's3://' to 's3:/'
's3:/mybucket/foo/bar'
Run Code Online (Sandbox Code Playgroud)

  • 关于 os.path.join 的注释:“如果任何组件是绝对路径,则所有先前的路径组件将被丢弃。” 所以你可能想`.lstrip("/")`你的参数。 (2认同)