杰瑞科技汇

python scp windows

Of course! Performing an SCP (Secure Copy) operation from a Python script on a Windows machine is a common task. The key challenge is that Windows does not have an scp command built-in like Linux or macOS.

python scp windows-图1
(图片来源网络,侵删)

You have two main approaches:

  1. Using a Python Library (Recommended): This is the most robust and "Pythonic" way. The library handles the SSH protocol for you, so you don't need to manage external executables.
  2. Using the Command Line: You can call an external scp executable (like from OpenSSH or PuTTY) from your Python script. This is simpler for one-off scripts but less portable.

Let's cover both in detail.


Approach 1: Using a Python Library (Recommended)

The best library for this is paramiko. It's a pure Python implementation of the SSHv2 protocol, which includes the functionality for SCP.

Step 1: Install paramiko

First, you need to install the library. Open your command prompt or PowerShell and run:

python scp windows-图2
(图片来源网络,侵删)
pip install paramiko

Step 2: Write the Python Script

paramiko provides two main ways to copy files:

  • SFTPClient: A more general-purpose file transfer protocol, similar to FTP but over SSH. It's highly recommended for most use cases.
  • SCPClient: A simpler, more direct implementation of the scp protocol. It's great for quick, straightforward copies.

Here are examples for both.

Example A: Using SFTP (Recommended for most cases)

SFTP is generally more flexible and reliable. It can handle recursive directories more cleanly and provides better error handling.

import paramiko
import os
# --- Configuration ---
# Replace with your server details
HOSTNAME = 'your.server.com'
USERNAME = 'your_username'
PASSWORD = 'your_password'  # Or use SSH key authentication (more secure)
# Local file path on Windows
LOCAL_PATH = r'C:\Users\YourUser\Documents\local_file.txt'
# Remote path on the server
REMOTE_PATH = '/home/your_username/remote_file.txt'
# --- SSH and SFTP Setup ---
try:
    # Create an SSH client
    ssh = paramiko.SSHClient()
    # Automatically add the server's host key (for security, consider using a known_hosts file instead)
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    # Connect to the server
    print(f"Connecting to {HOSTNAME}...")
    ssh.connect(hostname=HOSTNAME, username=USERNAME, password=PASSWORD)
    print("Connected successfully!")
    # Create an SFTP client from the SSH connection
    sftp = ssh.open_sftp()
    # --- File Transfer ---
    print(f"Uploading {LOCAL_PATH} to {REMOTE_PATH}...")
    # Use put() to upload a file
    sftp.put(LOCAL_PATH, REMOTE_PATH)
    print("Upload complete!")
    # --- Clean Up ---
    sftp.close()
    ssh.close()
except paramiko.AuthenticationException:
    print("Authentication failed, please verify your credentials.")
except paramiko.SSHException as sshException:
    print(f"Unable to establish SSH connection: {sshException}")
except FileNotFoundError:
    print(f"Local file not found: {LOCAL_PATH}")
except Exception as e:
    print(f"An error occurred: {e}")

Example B: Using SCPClient

This is a more direct translation of the scp command.

import paramiko
import os
# --- Configuration ---
HOSTNAME = 'your.server.com'
USERNAME = 'your_username'
PASSWORD = 'your_password'
LOCAL_PATH = r'C:\Users\YourUser\Documents\local_file.txt'
REMOTE_PATH = '/home/your_username/remote_file.txt'
# --- SSH and SCP Setup ---
try:
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    print(f"Connecting to {HOSTNAME}...")
    ssh.connect(hostname=HOSTNAME, username=USERNAME, password=PASSWORD)
    print("Connected successfully!")
    # Create an SCP client
    scp = paramiko.SCPClient(ssh.get_transport())
    # --- File Transfer ---
    print(f"Uploading {LOCAL_PATH} to {REMOTE_PATH}...")
    # Use put() to upload a file
    scp.put(LOCAL_PATH, REMOTE_PATH)
    print("Upload complete!")
    # --- Clean Up ---
    scp.close()
    ssh.close()
except paramiko.AuthenticationException:
    print("Authentication failed, please verify your credentials.")
except paramiko.SSHException as sshException:
    print(f"Unable to establish SSH connection: {sshException}")
except FileNotFoundError:
    print(f"Local file not found: {LOCAL_PATH}")
except Exception as e:
    print(f"An error occurred: {e}")

SSH Key Authentication (More Secure)

Hardcoding passwords is bad practice. It's much safer to use SSH keys.

  1. Generate an SSH key pair on your Windows machine using PuTTYgen or OpenSSH.
  2. Copy the public key to your server's ~/.ssh/authorized_keys file.
  3. Modify the Python script to use the private key.
import paramiko
# --- Configuration ---
HOSTNAME = 'your.server.com'
USERNAME = 'your_username'
# Path to your private key file on Windows
PRIVATE_KEY_PATH = r'C:\Users\YourUser\.ssh\id_rsa' 
LOCAL_PATH = r'C:\Users\YourUser\Documents\local_file.txt'
REMOTE_PATH = '/home/your_username/remote_file.txt'
try:
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    # Load the private key
    private_key = paramiko.RSAKey.from_private_key_file(PRIVATE_KEY_PATH)
    print(f"Connecting to {HOSTNAME} with key...")
    # Connect using the private key instead of a password
    ssh.connect(hostname=HOSTNAME, username=USERNAME, pkey=private_key)
    print("Connected successfully!")
    sftp = ssh.open_sftp()
    sftp.put(LOCAL_PATH, REMOTE_PATH)
    print("Upload complete!")
    sftp.close()
    ssh.close()
except paramiko.AuthenticationException:
    print("Authentication failed. Is the correct key added to the server?")
except paramiko.SSHException as e:
    print(f"SSH connection error: {e}")
except FileNotFoundError:
    print(f"Private key not found at {PRIVATE_KEY_PATH}")

Approach 2: Using the Command Line

This method involves calling an external scp.exe program from within your Python script. This is useful if you already have scp available or prefer a shell-like approach.

Step 1: Get an scp Executable for Windows

You need to install an SSH client that includes scp. The easiest way is to use OpenSSH for Windows.

  1. Check if it's already installed: Open PowerShell or Command Prompt and run scp. If it shows a help message, you're good to go.
  2. Install it: If not, you can install it via "Settings" -> "Apps" -> "Optional Features" -> "Add a feature" and search for "OpenSSH Client". Alternatively, if you use the Windows Subsystem for Linux (WSL), it will come pre-installed.

Step 2: Write the Python Script

You can use Python's built-in subprocess module to run the command.

import subprocess
import os
# --- Configuration ---
# Replace with your server details
HOSTNAME = 'your.server.com'
USERNAME = 'your_username'
PASSWORD = 'your_password' # WARNING: Passing passwords via CLI can be insecure.
# Local file path on Windows
LOCAL_PATH = r'C:\Users\YourUser\Documents\local_file.txt'
# Remote path on the server
REMOTE_PATH = f'{USERNAME}@{HOSTNAME}:/home/{USERNAME}/remote_file.txt'
# --- Command Construction ---
# Note: For security, using SSH keys is strongly preferred over passwords.
# The -o flag allows passing options, like BatchMode for non-interactive password auth.
# This method is less secure as the command line can be seen by other users.
command = [
    'scp',
    '-o', 'BatchMode=no',  # Allow interactive password prompt
    '-o', 'StrictHostKeyChecking=no', # Automatically accept new host keys (use with caution)
    LOCAL_PATH,
    REMOTE_PATH
]
print(f"Executing command: {' '.join(command)}")
# --- Execute the Command ---
try:
    # The input parameter sends the password to the scp process's stdin
    process = subprocess.Popen(
        command,
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        text=True,
        shell=True # Using shell=True can be easier with complex commands and paths
    )
    # Send the password to the process's standard input
    stdout, stderr = process.communicate(input=PASSWORD + '\n')
    if process.returncode == 0:
        print("File uploaded successfully!")
        print("Output:", stdout)
    else:
        print(f"Error uploading file. Return code: {process.returncode}")
        print("Error output:", stderr)
except FileNotFoundError:
    print("Error: 'scp' command not found. Please ensure OpenSSH Client is installed and in your PATH.")
except Exception as e:
    print(f"An unexpected error occurred: {e}")

Comparison and Recommendation

Feature Python Library (paramiko) Command Line (subprocess)
Portability Excellent. Runs anywhere Python is installed. No external dependencies. Poor. Requires scp to be installed and configured on the target machine.
Security Excellent. Can securely use SSH keys without exposing them. Passwords are handled internally. Poor. Passing passwords via command-line arguments is insecure. Keys are better, but still relies on an external binary.
Error Handling Good. You can catch specific paramiko exceptions. Fair. You get a return code and stderr, but parsing it can be more complex.
Ease of Use Moderate. Requires learning the paramiko API. Simple. If you know the scp command, it's straightforward to call it.
Features Excellent. Not just SCP, but full SSH capabilities (run commands, port forwarding, etc.). Limited. Only what the scp binary provides.

Final Recommendation:

Use the paramiko library. It is the standard, most secure, and most flexible way to handle file transfers and SSH operations in Python. The command-line approach is a quick fix but should be avoided for production or secure applications.

分享:
扫描分享到社交APP
上一篇
下一篇