Why would shutil.copy() raise a permission exception when cp doesn't?
Asked Answered
M

6

41

shutil.copy() is raising a permissions error:

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')

I am running copy-test.py from the command line:

python copy-test.py

But running cp from the command line on the same file to the same destination doesn't cause an error. Why?

Mckenziemckeon answered 6/8, 2012 at 20:58 Comment(1)
Could you please write the way you start the script and maybe source code of copy-test.py?Radiochemistry
B
74

The operation that is failing is chmod, not the copy itself:

  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'

This indicates that the file already exists and is owned by another user.

shutil.copy is specified to copy permission bits. If you only want the file contents to be copied, use shutil.copyfile(src, dst), or shutil.copyfile(src, os.path.join(dst, os.path.basename(src))) if dst is a directory.

A function that works with dst either a file or a directory and does not copy permission bits:

def copy(src, dst):
    if os.path.isdir(dst):
        dst = os.path.join(dst, os.path.basename(src))
    shutil.copyfile(src, dst)
Brassbound answered 6/8, 2012 at 21:8 Comment(2)
@JustinY you can use shutil.copyfile; see above.Brassbound
It was very helpful, the exact explanation!Sillabub
F
4

This form worked for me:

shutil.copy('/src_path/filename','/dest_path/filename')
Front answered 13/6, 2019 at 13:1 Comment(1)
To elaborate, you must specify the destination as a file path. I.e. you can't just copy to a directory path!Lucan
M
4

I had this exact same issue... using shutil.copyfile() was a good workaround.... however, I completely FIXED the issue by simply rebooting Windows 10 OS.

Manwell answered 24/7, 2022 at 22:47 Comment(0)
A
1

This work for me:

I don't use shutil I use shell command for copy, and run shell command in python.

Code:

import os

my_source= '/src_path/filename'
my_dest=   '/dest_path/filename'
os.system('sudo cp ' +my_source + my_dest ) # 'sudo cp /src_path/filename /dest_path/filename '

and that work for me.

Anadromous answered 7/2, 2023 at 16:15 Comment(1)
Your answer doesn't really answer the user's question. The question was "why does this happen"Surrebuttal
B
-1

This is kind of a guess, but the first thing that pops out at me:

'bin/styles/blacktie/images'

You have no trailing slash. While I'm not sure of the implementation of shutil.copy(), I can tell you that cp will act differently depending on what OS you're running it on. Most likely, on your system, cp is being smart and noticing that images is a directory, and copying the file into it.

However, without the trailing slash, shutil.copy() may be interpreting it as a file, not checking, and raising the exception when it's unable to create a file named images.

In short, try this:

'bin/styles/blacktie/images/'
Blotter answered 6/8, 2012 at 21:4 Comment(1)
Good guess but adding the trailing slash didn't solve my problem.Mckenziemckeon
C
-2

Arguments must be:

shutil.copy('src/images/ajax-loader-000000-e3e3e3.gif', 'bin/styles/blacktie/images.ajax-loader-000000-e3e3e3.gif')
Collectivity answered 9/2, 2018 at 8:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.