Disable SameFileError exception in shutil.copy
Asked Answered
S

2

8

I have the following code because sometimes these files will be the same and sometimes they won't.

import shutil
try:
   shutil.copy('filea','fileb')
   shutil.copy('filec','filed')
except shutil.SameFileError
   pass

The problem is that the second copy won't happen if the first copy has the same file.

Any suggestions on how to work around this? I don't see an argument in the shutil documentation that disables this check.

Scalp answered 17/7, 2019 at 20:22 Comment(0)
B
5

You can just separate the copy calls:

try:
  shutil.copy('filea','fileb')
except shutil.SameFileError:
  pass
    
try:
  shutil.copy('filec','filed')
except shutil.SameFileError:
  pass

Or put these four lines in a function.

copy_same_file_pass(src, dst):
  try:
    shutil.copy(src,dst)
  except shutil.SameFileError:
    pass

copy_same_file_pass('filea','fileb'):
copy_same_file_pass('filec','filed'):

Bahrain answered 11/12, 2020 at 21:31 Comment(0)
E
0

There is a not very elegant solution for it. I don't really recommend this solution. But it's up to you :)

The shutil._samefile function check if the source and destination files are the same (It will be called always, so the copy doesn't have any option to deactivate it). If the return value is True (So the files are the same), the SameFileError exception will be raised (As you can see below).

if _samefile(src, dst):
    raise SameFileError("{!r} and {!r} are the same file".format(src, dst))

You can force _samefile function to return False in every case.

import shutil


def my_same_file_diff_checker(*args, **kwargs):
    return False


shutil._samefile = my_same_file_diff_checker


shutil.copy("test.ini", "test.ini")

Important:

With this solution the SameFileError won't be raised but the copy function other parts will be ran. It means eg. the time-stamp of the file will be updated. As you can see below, the content of file will be re-written in file.

with open(src, 'rb') as fsrc:
    with open(dst, 'wb') as fdst:
        copyfileobj(fsrc, fdst)

Other (perhaps more elegant) solutions:

  • I recommend to use 2 separated try-except (As @hko has written)
  • Check the paths of files before the copy (Probably most Pythonic solution).
  • Write own copy function/method
Eclair answered 1/2, 2021 at 14:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.