使用Python通过SSH从服务器读取文件

时间:2009-10-20 20:04:00

标签: python ssh paramiko

我正在尝试使用来自Python的SSH从服务器读取文件。我正在使用Paramiko进行连接。我可以连接到服务器并运行cat filename之类的命令并从服务器返回数据,但我尝试读取的一些文件大小约为1 GB。

如何使用Python逐行读取服务器上的文件?

附加信息:经常做的是运行cat filename命令并将结果存储在变量中并解决该问题。但由于这里的文件很大,我正在寻找一种逐行读取文件的方法。

编辑:我可以读取一堆数据并将其拆分成行,但问题是缓冲区中接收的数据并不总是包含完整的行。例如,如果缓冲区有300行,则最后一行可能只是服务器上行的一半,下一半将在下次调用服务器时获取。我想要完整的行

编辑2:我可以使用什么命令在特定范围内的文件中打印行。喜欢打印前100行,那么接下来的100行等等?这样缓冲区将始终包含完整的行。

5 个答案:

答案 0 :(得分:54)

Paramiko's SFTPClient class允许您获取类似文件的对象,以Pythonic方式从远程文件中读取数据。

假设你有一个开放的SSHClient

sftp_client = ssh_client.open_sftp()
remote_file = sftp_client.open('remote_filename')
try:
    for line in remote_file:
        # process line
finally:
    remote_file.close()

答案 1 :(得分:10)

以下是@Matt Good's answer的扩展名:

from contextlib     import closing
from fabric.network import connect

with closing(connect(user, host, port)) as ssh, \
     closing(ssh.open_sftp()) as sftp, \
     closing(sftp.open('remote_filename')) as file:
    for line in file:
        process(line)

答案 2 :(得分:5)

#!/usr/bin/env python
import paramiko
import select
client = paramiko.SSHClient()
client.load_system_host_keys()
client.connect('yourhost.com')
transport = client.get_transport()
channel = transport.open_session()
channel.exec_command("cat /path/to/your/file")
while True:
  rl, wl, xl = select.select([channel],[],[],0.0)
  if len(rl) > 0:
      # Must be stdout
      print channel.recv(1024)

答案 3 :(得分:4)

“逐行”是什么意思 - 网络主机之间有很多数据缓冲区,而且没有一个是面向行的。

所以你可以读取一堆数据,然后将它分成近端的行。

ssh otherhost cat somefile | python process_standard_input.py | do_process_locally

或者你可以让一个进程读取远端的一堆数据,将其分解,然后逐行格式化并发送给你。

scp process_standard_input.py otherhost
ssh otherhost python process_standard_input.py somefile |  do_process_locally

我唯一关心的是减少有限网络管道上的数据量的方法。在你的情况下它可能,也可能不重要。

通过SSH管道使用cat来移动千兆字节的数据通常没有错。

答案 4 :(得分:0)

似乎早在2013年9月,paramiko就为这些对象添加了原生支持上下文管理器的功能,因此,如果您想同时使用Matt's clean answerjfs's context manager,那么您所需要做的就是:

with ssh_client.open_sftp() as sftp_client:
    with sftp_client.open('remote_filename') as remote_file:
        for line in remote_file:
            # process line