43

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

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

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

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

编辑 2:我可以使用什么命令在某个范围内的文件中打印行。就像打印前 100 行,然后打印下 100 行等等?这样缓冲区将始终包含完整的行。

4

5 回答 5

77

Paramiko 的SFTPClient允许您获取一个类似文件的对象,以便以 Python 方式从远程文件中读取数据。

假设你有一个 open 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()
于 2009-10-20T22:53:20.787 回答
13

这是@Matt Good 的答案的扩展,使用了fabric

from fabric.connection import Connection

with Connection(host, user) as c, c.sftp() as sftp,   \
         sftp.open('remote_filename') as file:
    for line in file:
        process(line)

旧面料 1 个回答:

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)
于 2009-10-21T03:15:19.340 回答
7
#!/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)
于 2009-10-20T20:12:03.390 回答
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

我关心的唯一区别是如何减少有限网络管道上的数据量。在您的情况下,它可能重要,也可能无关紧要。

使用catSSH 管道传输千兆字节的数据通常没有任何问题。

于 2009-10-20T20:11:21.893 回答
2

看起来早在 2013 年 9 月 paramiko 就增加了这些对象原生支持上下文管理器的能力,所以如果你想要马特的干净答案jfs 的上下文管理器,现在你只需要:

with ssh_client.open_sftp() as sftp_client:
    with sftp_client.open('remote_filename') as remote_file:
        for line in remote_file:
            # process line
于 2020-06-19T19:28:16.387 回答