1

PyFilesystemの Python 3.X サポートの改善に取り組んでいます。ファイルシステムの抽象化です。各ファイルシステム オブジェクトには、ファイルのようなオブジェクトを返す open メソッドがあります。

私が直面している問題は、open メソッドが Python 2.X で機能することですが、多数のバイナリ モードまたはテキスト モード ストリームの 1 つを返すopenように機能するようにしたいと考えています。io.open

私が使用できるのは、Python 2.X ファイルのようなオブジェクトを取得し、基になるファイルのようなオブジェクトに対して読み取り/書き込みを行う適切な io ストリーム オブジェクトを返す方法です (ただし、必要に応じてバッファリング/Unicode などを処理します)。

以下のようなことを考えていました。

def make_stream(file_object, mode, buffering, encoding):
    # return a io instance

標準ライブラリでそれを行う簡単な方法はわかりません。しかし、バッファリング/ユニコード機能を提供するソフトウェアレイヤーであるため、ioモジュールが内部で実行しなければならないことのように私には思えます。

4

1 に答える 1

1

Python 2 にも同じioライブラリが含まれています。

from io import openPython のバージョン間で同じように動作するために使用します。

次に、APIは、クラス ライブラリを使用して同じ機能を提供するopen()同等のもの (open()またはと呼ばれるmake_stream())を提供する必要があります。io

io.RawIOBaseABCを実装するクラスを作成し、ライブラリが提供する他のクラスを使用して、必要に応じてバッファリングとテキスト処理を追加するだけです。

import io

class MyFileObjectWrapper(io.RawIOBase):
    def __init__(self, *args):
        # do what needs done

    def close(self):
        if not self.closed:
            # close the underlying file
        self.closed = True

    # ... etc for what is needed (e.g. def read(self, maxbytes=None), etc.

def open(fileobj, mode='r', buffering=-1, encoding=None, errors=None, newline=None):
    # Mode parsing and validation adapted from the io/_iomodule.c module
    reading, writing, appending, updating = False
    text, binary, universal = False

    for c in mode:
        if c == 'r':
            reading = True;
            continue
        if c == 'w':
            writing = True;
            continue
        if c == 'a':
            appending = True;
            continue
        if c == '+':
            updating = True;
            continue
        if c == 't':
            text = True;
            continue
        if c == 'b':
            binary = True;
            continue
        if c == 'U':
            universal = reading = True;
            continue
        raise ValueError('invalid mode: {!r}'.format(mode))

    rawmode = []
    if reading:   rawmode.append('r')
    if writing:   rawmode.append('w')
    if appending: rawmode.append('a')
    if updating:  rawmode.append('+')
    rawmode = ''.join(rawmode)

    if universal and (writing or appending):
        raise ValueError("can't use U and writing mode at once")

    if text and binary) {
        raise ValueError("can't have text and binary mode at once")

    if reading + writing + appending > 1:
        raise ValueError("must have exactly one of read/write/append mode")

    if binary
        if encoding is not None:
            raise ValueError("binary mode doesn't take an encoding argument")
        if errors is not None:
            raise ValueError("binary mode doesn't take an errors argument")
        if newline is not None:
            raise ValueError("binary mode doesn't take a newline argument")

    raw = MyFileObjectWrapper(fileobj)

    if buffering == 1:
        buffering = -1
        line_buffering = True
    else:
        line_buffering = False

    if buffering < 0:
        buffering = SOME_SUITABLE_DEFAULT

    if not buffering
        if not binary:
            raise ValueError("can't have unbuffered text I/O")

        return raw

    if updating:
        buffered_class = io.BufferedRandom
    elif writing or appending:
        buffered_class = io.BufferedWriter
    elif reading:
        buffered_class = io.BufferedReader

    buffer = buffered_class(raw, buffering)

    if binary:
        return buffer

    return io.TextIOWrapper(buffer, encoding, errors, newline, line_buffering)

上記のコードは、主にModules/_io/_iomodule.c io_open関数から改作されていますが、未加工のファイル オブジェクトがABCのMyFileObjectWrapperサブクラスに置き換えられています。io.RawIOBase

于 2013-03-25T10:55:46.920 に答える