2015-11-10 3 views
14

ich versuche, eine Datei zu kopieren, mit pathlibCopy-Datei mit pathlib in Python

import pathlib 
import shutil 

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

bekomme ich diese Ausnahme:

/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 

... wie Datei mit pathlib in Python 2.7 zu kopieren?

+3

Dies funktioniert, ohne einen Fehler auf Python 3,6 – Anthon

+0

@Anthon werfen wir verwenden Python 2.7. – guettli

Antwort

13

Also was ist das?

import pathlib 
import shutil 

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

Das Problem ist pathlib.Path ein PosixPath Objekt erstellen, wenn Sie Unix/Linux verwenden, WindowsPath, wenn Sie Microsoft Windows verwenden.

Aber shutil.copy() brauchen Zeichenfolge als Argumente. Verwenden Sie also einfach str() hier, wenn Sie str() Funktion auf einem Path Objekt verwenden, wird es den ursprünglichen Pfad zurückgeben.

+0

Wenn ich das Problem richtig verstanden habe, dann ist der Code nicht portierbar: 'as_posix()' funktioniert nicht im Fenster. OK, '/ etc/hosts' existiert nicht in Windows, aber das Pfadobjekt könnte aus einer Konfiguration erstellt werden, die einen Windows-Pfad" C: \ .... "definiert. Gibt es keine tragbare Lösung? – guettli

+0

@guettli Bearbeitet, ich habe vergessen, wir können einfach 'str()' hier verwenden: P –

+0

@guettli Eigentlich, wenn Sie 'my_file.as_posix()' auf Windows verwenden, gibt es 'C:/etc/hosts' zurück . Das ist also egal. –

5

Die Ursache für shutil.copy() nicht funktioniert ist, dass Sie nicht den neuesten Python verwenden, Python 3.6 shutil.copy()könnenPath Objekte (oder Unterklassen davon) verarbeiten. Für ältere Versionen von Python ist dies ein Fehler, da diese Implementierungen von shutil String-Argumente für copy und nicht pathlib.Path Typargumente erwarten.

Was Sie eigentlich schreiben können, wollen, ist:

my_file.copy(to_file) 

Sie Pfad Unterklasse kann, ein solches Verfahren umfassen, und die Schaffung von my_file anzupassen. Ich finde es einfacher, nur Graft/Affe-Patch/Ente-Punsch auf der bestehenden 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 

Sie diesen Code überall hinstellen kann man so will, solange es vor dem Aufruf des .copy Methode auf einem der ausgeführt wird die Path Instanzen. Das Argument .copy() kann eine Datei oder ein Verzeichnis sein.

+1

AFAIK das heißt Monkey-Patching. Warum liefert pathlib das nicht? – guettli

+0

@guettli Vermutlich aus dem gleichen Grund muss man 'copy' von' shutyl' importieren: jemand dachte, es sei nicht nötig. Ich habe eine Reihe solcher Affen-Patches in meiner 'ruamel.std.pathlib'-Bibliothek und einige unterstützende Routinen für den Übergang zu pathlib (was mit den Änderungen in 3.6 teilweise überflüssig ist) – Anthon

+1

Ich denke, das ist der Grund, warum pathlib nicht breit ist Akzeptanz (nach meinem Standpunkt). Eine gute Nachricht ist, dass die Situation besser wird mit Python 3.6 – guettli

3

Sie können die pathlib rename-Methode anstelle von shutyl.move() verwenden.

import pathlib 

my_file = pathlib.Path('/etc/hosts') 
to_file = pathlib.Path('/tmp/foo') 
myfile.rename(to_file) 
2

Seit Python 3.5, ohne shutil zu importieren, können Sie tun:

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 

für Python 2.7, pathlib2 stellt die read_bytes, read_ext, write_bytes und write_text Methoden.

+0

Gibt es eine Möglichkeit, dies mit Python 2.7 zu tun? – guettli

+1

Es gibt etwas für Python 2.7, nämlich 'pathlib2', aber ich habe es nicht versucht. https://pypi.python.org/pypi/pathlib2/. Die 'read_bytes' und' write_bytes' Methoden sind im Quellcode, also nehme ich an, dass sie funktionieren. –

+1

@JacquesGaudin 'pathlib2' funktioniert perfekt. –