我需要透明地使用远程文件,好像它们是我正在写的一些python代码中的本地文件,所以我决定使用SFTP来完成这项任务。以下代码示例有效(它打印远程文件的第一行):
import paramiko
client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(hostname='192.168.8.103', username='root', password='pyjamas')
sftp = client.open_sftp()
test = sftp.open('/var/log/example/ingest.log', mode='r', bufsize=1)
print test.readline()
我将要连接到许多文件,所以我决定写一个给我一个SFTPFile对象的类。检查以下代码:
import paramiko
class RemoteLog(object):
"""This class implements the remote log buffer."""
def __init__(self, host, user='', pw='', log=''):
"""Initializes a connection to a remote log."""
client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(hostname=host, username=user, password=pw)
sftp = client.open_sftp()
self.log = sftp.open(log, mode='r', bufsize=1)
if __name__ == "__main__":
test = RemoteLog(host='192.168.8.103', user='root', pw='pyjamas', log='/var/log/example/ingest.log')
print test.log.readline()
不幸的是,此场景中的readline()不返回任何内容。没有错误或明显的解释。
我应该如何将我的第一个代码段中的功能复制到可重用的类中?
答案 0 :(得分:2)
当变量超出__init__
范围时,似乎关闭了sftp连接。存储对类中的引用的引用可以解决问题。
def __init__(self, host, user='', pw='', log=''):
"""Initializes a connection to a remote log."""
self.client = paramiko.SSHClient()
self.client.load_system_host_keys()
self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.client.connect(hostname=host, username=user, password=pw)
self.sftp = self.client.open_sftp()
self.log = self.sftp.open(log, mode='r', bufsize=1)
作为额外的建议,您可以考虑实现标准文件对象函数并隐藏对象后面的self.log引用。当您尝试包装类似文件的对象时,您应该能够使用test.log.readline()
而不是test.readline()
,而您应该真正实现close()
方法。有一些工作要做,但这是一次性的努力,并将使使用这个类的代码更清洁。