2

I'm trying to write a script to copy files in my RaspberryPi, from my Desktop PC. Here is my code: (a part)

print "start the copy"   
path_pi = '//192.168.2.2:22/home/pi/Stock/'
file_pc = path_file + "/" + file
print "the file to copy is: ", file_pc

shutil.copy2(file_pc, path_pi + file_pi)

Actually I have this error: (in french)

IOError: [Errno 2] Aucun fichier ou dossier de ce type: '//192.168.2.2:22/home/pi/Stock/exemple.txt'

So, how could I proceed? Must I connect the 2 machines before trying to copy? I have tryed with:

path_pi = r'//192.168.2.2:22/home/pi/Stock'

But the problem is the same. (And file_pc is a variable)

Thanks

Edit: Ok, I found this:

command = 'scp', file_pc, file_pi  
p = subprocess.Popen(command, stdout=subprocess.PIPE) 

But no way to have the output... (work with Shell=False)

Guillaume
  • 2,752
  • 5
  • 27
  • 42
  • related: [How do I copy a file to a remote server in python using scp or ssh?](http://stackoverflow.com/q/68335/4279) – jfs Mar 28 '14 at 11:06

2 Answers2

2

Do you have SSH enabled? Something like this could help you:

import os
os.system("scp FILE USER@SERVER:PATH")
PabloRosales
  • 348
  • 3
  • 11
  • While this should work, this isn't really a good idea. Using `subprocess.call(['scp', filename, '{}@{}:{}'.format(user, hostname, path)])` would be a bit cleaner. `os.system` is spawning a shell, and evaluating the text, which is both unnecessary and can lead to easy security vulnerabilities if you are putting any user input into that field. – wolfd Aug 25 '17 at 02:50
2

shutil.copy2() works with local files. 192.168.2.2:22 suggests that you want to copy files over ssh. You could mount the remote directory (RaspberryPi) onto a local directory on your desktop machine (sshfs) so that shutil.copy2() would work.

If you want to see the output of a command then don't set stdout=PIPE (note: if you set stdout=PIPE then you should read from p.stdout otherwise the process may block forever):

from subprocess import check_call

check_call(['scp', file_pc, file_pi])

scp will print to whatever places your parent Python script prints.

To get the output as a string:

from subprocess import check_output

output = check_output(['scp', file_pc, file_pi])

Though It looks like scp doesn't print anything by default if the output is redirected.

You could use pexpect to make scp think that it runs in a terminal:

import pipes
import re
import pexpect # $ pip install pexpect

def progress(locals):
    # extract percents
    print(int(re.search(br'(\d+)%[^%]*$', locals['child'].after).group(1)))

command = "scp %s %s" % tuple(map(pipes.quote, [file_pc, file_pi]))
status = pexpect.run(command, events={r'\d+%': progress}, withexitstatus=1)[1]
print("Exit status %d" % status)
jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • Thank you, it's work fine. How can I get the callback in a string? – Guillaume Mar 27 '14 at 18:10
  • @Guillaume: I've updated the answer to show how to get subprocess' output – jfs Mar 27 '14 at 18:14
  • Ok, but: out = check_output(['scp', file_pc, file_pi]) print out Nothing appers, it stay at the first line. In fact, I would like to get the percentage for a progressbar – Guillaume Mar 27 '14 at 19:16
  • @Guillaume: [update your question](http://stackoverflow.com/posts/22687296/edit) or [ask a new one](http://stackoverflow.com/questions/ask) specifically about how to get the percentage from scp command. – jfs Mar 27 '14 at 19:27
  • @Guillaume: I've added `pexpect`-based solution that can extract progress information from `scp` – jfs Mar 27 '14 at 20:09
  • Thanks for your help, but I will try to import the paramiko module, seems to be easier to use. – Guillaume Mar 28 '14 at 09:19
  • @Guillaume: try [`fabric`](http://fabfile.org) it is built on top of `paramiko`. See [How do I copy a directory to a remote machine using Fabric?](http://stackoverflow.com/q/5314711/4279). btw, I doubt that `paramiko` code is simpler than `pexpect`. Here's a [code example of downloading using paramiko](http://stackoverflow.com/a/20381739/4279). – jfs Mar 28 '14 at 09:32
  • I've asked a new [question](http://stackoverflow.com/questions/22708942/python-paramiko-module-error-with-callback) with paramiko module, because it's almost successful. For fabric, I havn't tested yet. – Guillaume Mar 28 '14 at 09:43
  • The pexpect solution works fine. The def progress(local) must be placed inside another def(self, data). – Guillaume Mar 28 '14 at 14:32