Howe to get ORDSYS.ORDIMAGE field value in python
<p>Using cx_Oracle 5.2.1 with Oracle client library 11.2 and Oracle server 11.2, I am unable to retrieve the content of an <code>ORDSYS.ORDIMAGE</code> field.
The following code raises <code>attribute read not found exception</code>:</p>

<pre><code>import cx_Oracle
db = cx_Oracle.Connection('user/pass@ip/t')
cursor = db.cursor()
cursor.execute("select IMAGE from T where ROWID in ('AAAAAAAAAA')")
bf, = cursor.fetchone()
bfile_data = bf.read()
</code></pre>

<p>The exception raised is: <code>AttributeError: 'cx_Oracle.OBJECT' object has no attribute 'read'</code></p>

<p>The problem is that cx_Oracle.OBJECT does not have a read() method. Instead, it has attributes which you can read/write just like any other Python object.</p>

<p>Using the unreleased version of cx_Oracle the following generic code will work:</p>

<pre><code>def ObjectRepr(obj):
    if obj.type.iscollection:
        returnValue = []
        for value in obj.aslist():
            if isinstance(value, cx_Oracle.Object):
                value = ObjectRepr(value)
            returnValue.append(value)
    else:
        returnValue = {}
        for attr in obj.type.attributes:
            value = getattr(obj, attr.name)
            if value is None:
                continue
            elif isinstance(value, cx_Oracle.Object):
                value = ObjectRepr(value)
            returnValue[attr.name] = value
    return returnValue

print(ObjectRepr(bf))
</code></pre>

<p>If you are using 5.2.1, though, some of the introspective code is not available. Fortunately, you don't need that. You can describe the type in SQL*Plus which will show you the list of attributes at the beginning of its output</p>

<pre><code>desc ordsys.ordimage
</code></pre>

<p>That should allow you to do the following in your Python code:</p>

<pre><code>print(bf.HEIGHT)
print(bf.WIDTH)
print(bf.CONTENTLENGTH)
print(bf.FILEFORMAT)
</code></pre>

<p>Note that the attribute SOURCE is yet another object so you can access its attributes in the same way:</p>

<pre><code>print(bf.SOURCE.SRCNAME)
print(bf.SOURCE.UPDATETIME)
</code></pre>

<p>and so forth.</p>

<p>The attribute bf.SOURCE.LOCALDATA is of type BLOB which is currently unsupported. You can access its value using an anonymous PL/SQL block instead:</p>

<pre><code>var = cursor.var(cx_Oracle.BLOB)
cursor.execute("""
        declare
            t_Image ordsys.ordimage;
        begin
            select Image
            into t_Image
            from T
            where rownum &lt;= 1;

            :1 := t_Image.source.localdata;

        end;""", (var,))
blob = var.getvalue()
print("Image data is:", blob.read())
</code></pre>

python oracle cx-oracle