Skip to content

Enhancement: How to use LOBs like streams (in a file-like way)? #128

Description

@hvbtup

This is not a cx_Oracle error, but an enhancement request.

I would like to use a CLOB in a way compatible to io.TextIOBase,
such that I can the usual read() and seek() methods.
This seems a very natural approach to me.

However, I can't get it to work.
The problem is specifying the encoding (for writing the content to a binary file later).
The TextIOBase class provides an attribute "encoding", but I cannot set it.

A very similar approach for BLOBs and io.RawIOBase does work fine
(of course, there is no encoding attribute then).

This is what I tried:

class UnbufferedClobReader(io.TextIOBase):
    """
    A file-like wrapper for a read-only cx_Oracle CLOB object.
    """
    def __init__(self, clobLocator, encoding):
        self.clobLocator = clobLocator
        self.offset = 0
        self.encoding = encoding
        self.size = clobLocator.size()

    def seekable(self):
        return True
    
    def seek(self, offset, whence):
        if whence == 0:
            self.offset = offset
        elif whence == 1:
            self.offset += offset
            if self.offset < 0:
                self.offset = 0
        elif whence == 2:
            if offset <= 0 and -offset <= self.size:
                self.offset = self.size + offset
            else:
                raise IOError(96, "Invalid offset for CBlobReader")
        else:
            self._unsupported("seek")
        return self.offset

    def readable(self):
        return True
    
    def read(self, size):
        size = min(self.size - self.offset, size)
        if size == 0:
            return ""
        chunk = self.clobLocator.read(self.offset + 1, size)
        assert len(chunk) == size
        self.offset += size
        return chunk

Note: Actually I only need the read method in my code.

The constructor fails with the exception
AttributeError: attribute 'encoding' of '_io._TextIOBase' objects is not writable

Any ideas how specifying the encoding (for when the stream has to be written to a byte stream) can be accomplished?

It would be fine if cx_Oracle provided such wrapper-classes directly.

  1. What is your version of Python? Is it 32-bit or 64-bit?
    3.6.4 win32-AMD64

  2. What is your version of cx_Oracle?
    6.0.3

  3. What is your version of the Oracle client (e.g. Instant Client)? How was it
    installed? Where is it installed?
    12.2.0.1.0 Instant Client (working fine)

  4. What is your version of the Oracle Database?
    12.1

  5. What is your OS and version?
    Windows

  6. What compiler version did you use? For example, with GCC, run
    n/a

  7. What environment variables did you set? How exactly did you set them?
    n/a

  8. What exact command caused the problem (e.g. what command did you try to
    install with)? Who were you logged in as?
    n/a

  9. What error(s) you are seeing?
    AttributeError: attribute 'encoding' of '_io._TextIOBase' objects is not writable

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions