web-dev-qa-db-ja.com

Pythonのpathlibでファイルをコピー

pathlibでファイルをコピーしようとしました

import pathlib
import shutil

my_file=pathlib.Path('/etc/hosts')
to_file=pathlib.Path('/tmp/foo')
shutil.copy(my_file, to_file)

私はこの例外を受け取ります:

/home/foo_egs_d/bin/python /home/foo_egs_d/src/test-pathlib-copy.py
Traceback (most recent call last):
  File "/home/foo_egs_d/src/test-pathlib-copy.py", line 6, in <module>
    shutil.copy(my_file, to_file)
  File "/usr/lib/python2.7/shutil.py", line 117, in copy
    if os.path.isdir(dst):
  File "/home/foo_egs_d/lib/python2.7/genericpath.py", line 41, in isdir
    st = os.stat(s)
TypeError: coercing to Unicode: need string or buffer, PosixPath found

Process finished with exit code

... Python 2.7でpathlibを使用してファイルをコピーする方法

38
guettli

これはどうですか?

_import pathlib
import shutil

my_file = pathlib.Path('/etc/hosts')
to_file = pathlib.Path('/tmp/foo')
shutil.copy(str(my_file), str(to_file))
_

問題は、Unix/Linuxを使用している場合は_pathlib.Path_ PosixPathオブジェクトを作成し、Microsoft Windowsを使用している場合はWindowsPathオブジェクトを作成することです。

ただし、shutil.copy()には引数として文字列が必要です。したがって、ここでstr()を使用してください。Pathオブジェクトでstr()関数を使用すると、元のパスが返されます。

31
Kevin Guan

shutil.copy()が機能しない原因は、最新のPythonを使用していないことです。Python 3.6 shutil.copy()can handle Pathオブジェクト(またはそのサブクラス)Pythonの古いバージョンでは、これはエラーをスローします。これは、shutilの実装がcopy、および_pathlib.Path_型の引数ではありません。

あなたが実際に書きたいのは:

_my_file.copy(to_file)
_

Pathをサブクラス化してこのようなメソッドを含め、_my_file_の作成を適応させることができます。既存の_pathlib.Path_に移植/猿パッチ/ダックパンチする方が簡単だと思います

_from pathlib import Path


def _copy(self, target):
    import shutil
    assert self.is_file()
    shutil.copy(str(self), str(target))  # str() only there for Python < (3, 6)

Path.copy = _copy
_

このコードは、Pathインスタンスの_.copy_メソッドを呼び出す前に実行される限り、好きな場所に置くことができます。 .copy()の引数には、ファイルまたはディレクトリを指定できます。

23
Anthon

Python 3.5、shutilをインポートせずに、以下を実行できます。

_from pathlib import Path

dest = Path('dest')
src = Path('src')
dest.write_bytes(src.read_bytes()) #for binary files
dest.write_text(src.read_text()) #for text files
_

Python 2.7、 _pathlib2_ は、_read_bytes_、_read_text_、_write_bytes_、および_write_text_を提供しますメソッド。

ファイルはメモリにロードされるため、この方法はマシンで利用可能なメモリよりも大きいファイルには適していません。

コメントによると、_write_bytes_と_read_bytes_を使用してテキストファイルをコピーできますが、コピー時にエンコードを処理する必要がある場合は_write_text_と_read_text_が有利です2つの追加パラメーター:

  • encodingは、ファイルのデコードまたはエンコードに使用されるエンコードの名前です
  • errorsは、エンコードおよびデコードエラーの処理方法を指定するオプションの文字列です。

両方とも open() と同じ意味を持ちます。

14
Jacques Gaudin

shutilがどのように変換されてPython 3.6)の_pathlib.Path_オブジェクトを受け入れるか

https://stackoverflow.com/a/40319071/895245 shutil in Python 3.6は_pathlib.Path_オブジェクトを取ることができます。

これは非常に魔法のように感じられたため、実装方法を少し調べて、この魔法を自分のクラスで再利用できるかどうかを確認することにしました。

改善はPEP 519の結果でした: https://www.python.org/dev/peps/pep-0519/

これにより多くのstdlib機能が一般化され、結果としてドキュメントは一貫して更新されませんでした。ほとんどのshutilは3.7 単一の関数でサポートされるドキュメントのみ です。ダイナミックタイピングの喜びへようこそ。

文書化されている場合、stlibは「パスのようなオブジェクト」の用語集にリンクしています。 https://docs.python.org/3/glossary.html#term-path-like-object

ファイルシステムパスを表すオブジェクト。パスのようなオブジェクトは、パスを表すstrまたはbytesオブジェクト、またはos.PathLikeプロトコルを実装するオブジェクトです。 os.PathLikeプロトコルをサポートするオブジェクトは、os.fspath()関数を呼び出すことにより、strまたはbytesファイルシステムパスに変換できます。代わりに、os.fsdecode()およびos.fsencode()を使用して、それぞれstrまたはbytesの結果を保証できます。 PEP 519で導入されました。

そして、それは_os.PathLike_のドキュメントにリンクします: https://docs.python.org/3/glossary.html#term-path-like-object

ファイルシステムパスを表すオブジェクトの抽象基本クラス。 pathlib.PurePath。

バージョン3.6の新機能。

abstractmethod __fspath__()

オブジェクトのファイルシステムパス表現を返します。

このメソッドはstrまたはbytesオブジェクトのみを返す必要があり、優先度はstrです。

主要な実装のコミットは次のようです:

独自のパスのようなクラスを実装する場合は、次のように実行できます。

_#!/usr/bin/env python3

class MyPath:
    def __init__(self, path):
        self.path = path
    def __fspath__(self):
        return self.path

with open(MyPath('f'), 'w'):
    pass
_

テスト済みPython 3.6.7、Ubuntu 18.10。

Shutil.move()の代わりに pathlib renameメソッドを使用できます。

import pathlib

my_file = pathlib.Path('/etc/hosts')
to_file = pathlib.Path('/tmp/foo')
my_file.rename(to_file)
4
Geoff D