如何使用Paramiko getfo从SFTP服务器下载文件到内存来处理它

时间:2018-05-25 14:35:10

标签: python pandas io sftp paramiko

我正在尝试使用Paramiko从SFTP下载CSV文件(内存中)并将其导入到pandas数据帧中。

public class FbAutomation {
    public static void main(String[] args) {
        FirefoxDriver browser = new FirefoxDriver();
        browser.get("https://www.facebook.com/");
        browser.manage().window().maximize();
        browser.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
        browser.findElement(By.xpath("//input[@name='email']")).sendKeys("user-email");
        browser.findElement(By.xpath("//input[@name='pass']")).sendKeys("password");
        /*Dimension radi = browser.findElement(By.xpath("//label[@id='loginbutton']")).getSize();
        System.out.println("height is " + radi.height + " and width is " + radi.width);*/
        browser.findElement(By.xpath("//label[@id='loginbutton']")).submit();
        browser.navigate().to("https://www.facebook.com/imshaiknasir");
        Alert alt = browser.switchTo().alert();
        alt.accept();
        /*
         * Not able to handle "Allow notification" popUp box.
         */`enter code here`
        browser.close();
    }
}

以下代码失败,告诉我:

  

OSError:文件未打开以供阅读

我认为我需要某种缓冲区或类似transport = paramiko.Transport((server, 22)) transport.connect(username=username, password=password) sftp = paramiko.SFTPClient.from_transport(transport) with open(file_name, 'wb') as fl: sftp.getfo(file_name, fl, callback=printTotals) df = pd.read_csv(fl, sep=' ') 的对象文件,因为open需要一个文件。我对这一切都比较陌生,所以如果有人可以提供帮助,我会很高兴。

2 个答案:

答案 0 :(得分:4)

仍允许您使用进度回调的简单解决方案是:

  • 使用BytesIO file-like object将下载的文件存储到内存中;
  • 在开始阅读之前,您必须在下载后将文件指针重新启动回文件开始。
with io.BytesIO() as fl:
    sftp.getfo(file_name, fl, callback=printTotals)
    fl.seek(0)
    df = pd.read_csv(fl, sep=' ')

虽然使用此解决方案,您最终会将文件加载到内存中两次。

更好的解决方案是实现类文件对象。它甚至允许您同时下载和解析文件。

class FileWithProgress:

    def __init__(self, fl):
        self.fl = fl
        self.size = fl.stat().st_size
        self.p = 0

    def read(self, blocksize):
        r = self.fl.read(blocksize)
        self.p += len(r)
        print(str(self.p) + " of " + str(self.size)) 
        return r

并使用它:

with sftp.open(file_name, "rb") as fl:
    fl.prefetch()
    df = pd.read_csv(FileWithProgress(fl), sep=' ') 

答案 1 :(得分:2)

我最终做的是一个简单的版本,遗憾的是没有回复进展,我还需要rb阅读:

with sftp.open(file_name, 'rb') as fl:
        df = pd.read_csv(fl, sep=' ')

无论如何,马丁的答案正是我所寻找的!