Python的FTPLIB:在写模式打开的文件?

问题描述 投票:0回答:1

我怎样才能在写模式下打开文件FTP服务器上?我知道我可以写/直接创建文件(当我有数据),但我想先打开写,然后才写这就像使用本地contextmanager做。

其理由是,我想创建界面,将有统一的方法与传输协议服务器的工作。具体SFTP和FTP。

因此,与SFTP其易(使用paramiko):

def open(sftp, fname, mode='r'):
    return sftp.open(fname, mode=mode)

现在,我可以这样做:

with open(sftp, 'some_file.txt', 'w') as f:
    f.write(data)

然后,我可以读到写

with open(sftp, 'some_file.txt', 'r') as f:
    print(f.read().decode('utf-8'))

我该怎么办的FTP(使用ftplib)相同的实现?

阅读部分的FTP,我能实现,我可以打开阅读模式文件就像与SFTP。但是,我怎么能在写模式下打开它?要被提供FTPLIB方法storbinary请求数据“立即”。我的意思是我应该已经通过数据我想通过open方法写入(但随后会破坏统一的方法,目的)?

import io

def open(ftp, filename, mode='r'):
    """Open a file on FTP server."""
    def handle_buffer(buffer_data):
        bio.write(buffer_data)

    # Reading implementation
    if mode == 'r':
        bio = io.BytesIO()
        ftp.retrbinary(
            'RETR %s' % filename, callback=handle_buffer)
        bio.seek(0)
        return bio
    # Writing implementation.
    if mode == 'w':
        # how to open in write mode?

更新

让我们说我们有FTP直接书写实现:

bio = io.BytesIO
# Write some data
data = csv.writer(bio)
data.writerows(data_to_export)
bio.seek(0)
# Store. So it looks like storbinary does not open file in w mode, it does everything in one go?
ftp.storbinary("STOR " + file_name, sio)

所以,问题是我如何从刚刚在写模式打开文件分开写入数据。它甚至有可能与FTPLIB?

python python-3.x file-writing ftplib
1个回答
0
投票

所以经过一番挣扎后,我能够做这项工作。解决方案是实现自定义contextmanagers为open方法时,在读(不得不重新实现读模式,因为它只是用纯文本文件的阅读工作,但未能要是让说,我会尝试使用CSV阅读器)模式下,当在写模式。

对于读模式下,我选择使用临时文件,因为用其他的方法,我是不是能够正确读取使用不同的阅读器(纯文本文件阅读器,CSV阅读等)的数据。虽然使用在读模式下临时文件打开时,一切正常。

对于写模式,我能够利用内存缓冲区 - > io.BytesIO。所以写这是没有必要使用临时文件。

import tempfile


class OpenRead(object):

    def _open_tempfile(self):
        self.tfile = tempfile.NamedTemporaryFile()
        # Write data on tempfile.
        self.ftp.retrbinary(
            'RETR %s' % self.filename, self.tfile.write)
        # Get back to start of file, so it would be possible to
        # read it.
        self.tfile.seek(0)
        return open(self.tfile.name, 'r')

    def __init__(self, ftp, filename):
        self.ftp = ftp
        self.filename = filename
        self.tfile = None

    def __enter__(self):
        return self._open_tempfile()

    def __exit__(self, exception_type, exception_value, traceback):
        # Remove temporary file.
        self.tfile.close()

class OpenWrite(object):
    def __init__(self, ftp, filename):
        self.ftp = ftp
        self.filename = filename
        self.data = ''

    def __enter__(self):
        return self

    def __exit__(self, exception_type, exception_value, traceback):
        bio = io.BytesIO()
        if isinstance(self.data, six.string_types):
            self.data = self.data.encode()
        bio.write(self.data)
        bio.seek(0)
        res = self.ftp.storbinary('STOR %s' % self.filename, bio)
        bio.close()
        return res

    def write(self, data):
        self.data += data

def open(ftp, filename, mode='r'):
    """Open a file on FTP server."""
    if mode == 'r':
        return OpenRead(ftp, filename)
    if mode == 'w':
        return OpenWrite(ftp, filename)

附:这可能不是没有上下文管理器正常工作,但现在它是确定的解决方案给我。如果任何人有更好的实施,他们非常欢迎分享。

更新

决定使用ftputil包,而不是标准ftplib。所以不需要这一切的黑客,因为ftputil需要照顾它,它实际上是使用了很多相同的命名方式为paramiko,是做同样的事情,所以它是非常容易统一协议的使用。

© www.soinside.com 2019 - 2024. All rights reserved.