How to scp in Python?

What's the most pythonic way to scp a file in Python? The only route I'm aware of is

os.system('scp "%s" "%s:%s"' % (localfile, remotehost, remotefile) )

which is a hack, and which doesn't work outside Linux-like systems, and which needs help from the Pexpect module to avoid password prompts unless you already have passwordless SSH set up to the remote host.

I'm aware of Twisted's conch, but I'd prefer to avoid implementing scp myself via low-level ssh modules.

I'm aware of paramiko, a Python module that supports SSH and SFTP; but it doesn't support SCP.

Background: I'm connecting to a router which doesn't support SFTP but does support SSH/SCP, so SFTP isn't an option.

EDIT: This is a duplicate of How to copy a file to a remote server in Python using SCP or SSH?. However, that question doesn't give an scp-specific answer that deals with keys from within Python. I'm hoping for a way to run code kind of like

import scp

client = scp.Client(host=host, user=user, keyfile=keyfile)
# or
client = scp.Client(host=host, user=user)
# or
client = scp.Client(host=host, user=user, password=password)

# and then
client.transfer('/etc/local/filename', '/etc/remote/filename')

Asked by: Kelvin897 | Posted: 24-09-2021

Answer 1

Try the Python scp module for Paramiko. It's very easy to use. See the following example:

import paramiko
from scp import SCPClient

def createSSHClient(server, port, user, password):
    client = paramiko.SSHClient()
    client.connect(server, port, user, password)
    return client

ssh = createSSHClient(server, port, user, password)
scp = SCPClient(ssh.get_transport())

Then call scp.get() or scp.put() to do SCP operations.

(SCPClient code)

Answered by: Julian437 | Posted: 25-10-2021

Answer 2

You might be interested in trying Pexpect (source code). This would allow you to deal with interactive prompts for your password.

Here's a snip of example usage (for ftp) from the main website:

# This connects to the openbsd ftp site and
# downloads the recursive directory listing.
import pexpect
child = pexpect.spawn ('ftp')
child.expect ('Name .*: ')
child.sendline ('anonymous')
child.expect ('Password:')
child.sendline ('')
child.expect ('ftp> ')
child.sendline ('cd pub')
child.expect('ftp> ')
child.sendline ('get ls-lR.gz')
child.expect('ftp> ')
child.sendline ('bye')

Answered by: Blake255 | Posted: 25-10-2021

Answer 3

Couldn't find a straight answer, and this "scp.Client" module doesn't exist. Instead, this suits me:

from paramiko import SSHClient
from scp import SCPClient

ssh = SSHClient()

with SCPClient(ssh.get_transport()) as scp:
   scp.put('test.txt', 'test2.txt')

Answered by: Patrick643 | Posted: 25-10-2021

Answer 4

You could also check out paramiko. There's no scp module (yet), but it fully supports sftp.

[EDIT] Sorry, missed the line where you mentioned paramiko. The following module is simply an implementation of the scp protocol for paramiko. If you don't want to use paramiko or conch (the only ssh implementations I know of for python), you could rework this to run over a regular ssh session using pipes. for paramiko

Answered by: Brad152 | Posted: 25-10-2021

Answer 5

if you install putty on win32 you get an pscp (putty scp).

so you can use the os.system hack on win32 too.

(and you can use the putty-agent for key-managment)

sorry it is only a hack (but you can wrap it in a python class)

Answered by: Cherry460 | Posted: 25-10-2021

Answer 6

As of today, the best solution is probably AsyncSSH

async with asyncssh.connect('host.tld') as conn:
    await asyncssh.scp((conn, 'example.txt'), '.', recurse=True)

Answered by: Carlos637 | Posted: 25-10-2021

Answer 7

You can use the package subprocess and the command call to use the scp command from the shell.

from subprocess import call

cmd = "scp user1@host1:files user2@host2:files"
call(cmd.split(" "))

Answered by: Dainton900 | Posted: 25-10-2021

Answer 8

import paramiko

client = paramiko.SSHClient()

client.connect('<IP Address>', username='<User Name>',password='' ,key_filename='<.PEM File path')

#Setup sftp connection and transmit this script 
print ("copying")

sftp = client.open_sftp() 
sftp.put(<Source>, <Destination>)


Answered by: Agata190 | Posted: 25-10-2021

Answer 9

Have a look at fabric.transfer.

from fabric import Connection

with Connection(host="hostname", 
                connect_kwargs={"key_filename": "/home/myuser/.ssh/private.key"}
               ) as c:
    c.get('/foo/bar/file.txt', '/tmp/')

Answered by: Adelaide431 | Posted: 25-10-2021

Answer 10

It has been quite a while since this question was asked, and in the meantime, another library that can handle this has cropped up: You can use the copy function included in the Plumbum library:

import plumbum
r = plumbum.machines.SshMachine("")
   # this will use your ssh config as `ssh` from shell
   # depending on your config, you might also need additional
   # params, eg: `user="username", keyfile=".ssh/some_key"`
fro = plumbum.local.path("some_file")
to = r.path("/path/to/destination/")
plumbum.path.utils.copy(fro, to)

Answered by: Miller520 | Posted: 25-10-2021

Answer 11

If you are on *nix you can use sshpass

sshpass -p password scp -o User=username -o StrictHostKeyChecking=no src dst:/path

Answered by: Ryan969 | Posted: 25-10-2021

Answer 12

Hmmm, perhaps another option would be to use something like sshfs (there an sshfs for Mac too). Once your router is mounted you can just copy the files outright. I'm not sure if that works for your particular application but it's a nice solution to keep handy.

Answered by: Walter996 | Posted: 25-10-2021

Answer 13

I while ago I put together a python SCP copy script that depends on paramiko. It includes code to handle connections with a private key or SSH key agent with a fallback to password authentication.

Answered by: Andrew903 | Posted: 25-10-2021

Similar questions

SSH twice with Python

This question already has an answer here:

python - What's the best Django search app?

How can I use a DLL file from Python?

What is the easiest way to use a DLL file from within Python? Specifically, how can this be done without writing any additional wrapper C++ code to expose the functionality to Python? Native Python functionality is strongly preferred over using a third-party library.

python - PubSub lib for c#

Is there a c# library which provides similar functionality to the Python PubSub library? I think it's kind of an Observer Pattern which allows me to subscribe for messages of a given topic instead of using events.

python - What is the best way to copy a list?

This question already has answers here:

python - Possible Google Riddle?

My friend was given this free google website optimizer tshirt and came to me to try and figure out what the front logo meant. t-shirt So, I have a couple of guesses as to what it means, but I was just wondering if there is something more. My first guess is that eac...

How do you check whether a python method is bound or not?

Given a reference to a method, is there a way to check whether the method is bound to an object or not? Can you also access the instance that it's bound to?

python - How do I create a new signal in pygtk

I've created a python object, but I want to send signals on it. I made it inherit from gobject.GObject, but there doesn't seem to be any way to create a new signal on my object.

python - What do I need to import to gain access to my models?

I'd like to run a script to populate my database. I'd like to access it through the Django database API. The only problem is that I don't know what I would need to import to gain access to this. How can this be achieved?

python - How do I edit and delete data in Django?

I am using django 1.0 and I have created my models using the example in the Django book. I am able to perform the basic function of adding data; now I need a way of retrieving that data, loading it into a form (change_form?! or something), EDIT it and save it back to the DB. Secondly how do I DELETE the data that's in the DB? i.e. search, select and then delete! Please show me an example of the code ...

python - How do I turn an RSS feed back into RSS?

According to the feedparser documentation, I can turn an RSS feed into a parsed object like this: import feedparser d = feedparser.parse('') but I can't find anything showing how to go the other way; I'd like to be able do manipulate 'd' and then output the result as XM...

Still can't find your answer? Check out these communities...

PySlackers | Full Stack Python | NHS Python | Pythonist Cafe | Hacker Earth | Discord Python