Почему shutil.copy() вызывает исключение разрешения, если cp не работает?

shutil.copy() вызывает ошибку разрешений:

Traceback (most recent call last):
  File "copy-test.py", line 3, in <module>
    shutil.copy('src/images/ajax-loader-000000-e3e3e3.gif', 'bin/styles/blacktie/images')
  File "/usr/lib/python2.7/shutil.py", line 118, in copy
    copymode(src, dst)
  File "/usr/lib/python2.7/shutil.py", line 91, in copymode
    os.chmod(dst, mode)
OSError: [Errno 1] Operation not permitted: 'bin/styles/blacktie/images/ajax-loader-000000-e3e3e3.gif'

copy-test.py:

import shutil

shutil.copy('src/images/ajax-loader-000000-e3e3e3.gif', 'bin/styles/blacktie/images')

Я запускаю copy-test.py из командной строки:

python copy-test.py

Но запуск cp из командной строки в том же файле в тот же пункт назначения не вызывает ошибки. Почему?

Ответы

Ответ 1

Выполняемая операция chmod, а не сама копия:

  File "/usr/lib/python2.7/shutil.py", line 91, in copymode
    os.chmod(dst, mode)
OSError: [Errno 1] Operation not permitted: 'bin/styles/blacktie/images/ajax-loader-000000-e3e3e3.gif'

Это означает, что файл уже существует и принадлежит другому пользователю.

shutil.copy указывается для копирования битов разрешения. Если вы хотите, чтобы содержимое файла было скопировано, используйте shutil.copyfile(src, dst) или shutil.copyfile(src, os.path.join(dst, os.path.basename(src))), если dst - это каталог.

Функция, которая работает с dst либо файлом, либо каталогом и не копирует бит разрешения:

def copy(src, dst):
    if os.path.isdir(dst):
        dst = os.path.join(dst, os.path.basename(src))
    shutil.copyfile(src, dst)

Ответ 2

Это своего рода догадка, но первое, что появляется у меня:

'bin/styles/blacktie/images'

У вас нет конечной косой черты. Хотя я не уверен в реализации shutil.copy(), могу сказать, что cp будет действовать по-разному в зависимости от того, на какой ОС вы его запускаете. Скорее всего, в вашей системе cp умнее и замечает, что images является каталогом и копирует файл в него.

Однако, без конечной косой черты, shutil.copy() может интерпретировать его как файл, а не проверять и поднимать исключение, когда он не может создать файл с именем images.

Короче говоря, попробуйте следующее:

'bin/styles/blacktie/images/'

Ответ 3

Аргументы должны быть:

shutil.copy('src/images/ajax-loader-000000-e3e3e3.gif', 'bin/styles/blacktie/images.ajax-loader-000000-e3e3e3.gif')

Ответ 4

Эта форма работала для меня:

shutil.copy('/src_path/filename','/dest_path/filename')