pythonoracle-databasecx-oracle

how can i get the dbms_Output in Python


I am trying to run a sql procedure in python. The running works but I don't get the dbms output that I get in oracle with the sql developer. Does anyone know how i can also get the dbms output. Here is my code how I call the procedure:

cursor.callproc('search', ('math', 'paris'))

Solution

  • If you are using cx_Oracle ( https://oracle.github.io/python-cx_Oracle/ ) then the code could be like this:

    import cx_Oracle
    #   make a connection & create cursor
    conn = cx_Oracle.connect('username', 'password', 'db')
    cur = conn.cursor()
    
    #   variable to colect serveroutputs into
    dbmsRet = ''
    
    #   SET SERVEROUTPUT ON 
    cur.callproc("dbms_output.enable")
    
    #   Pl/SQL Block
    mPlSql = """-- testing serveroutput --
    Declare 
        TestMsg VarChar2(50); 
    Begin    
        TestMsg := 'Test no. 1'; 
        DBMS_OUTPUT.PUT_LINE(TestMsg); 
        TestMsg := Chr(9) || TestMsg || Chr(10) || Chr(9) || 'Test no. 2'; 
        DBMS_OUTPUT.PUT_LINE(TestMsg); 
    End;
    """
    
    #   Execute
    mCmd = "cur.execute(mPlSql)"
    exec(mCmd)
    
    chunk = 100
    # create variables to hold the output
    mLine = cur.arrayvar(str, chunk)
    mNumLines = cur.var(int)
    mNumLines.setvalue(0, chunk)
    
    # fetch the text that was added by PL/SQL
    while True:
        cur.callproc("dbms_output.get_lines", (mLine, mNumLines))
        num_lines = int(mNumLines.getvalue())
        lines = mLine.getvalue()[:num_lines]
        for line in lines:
            dbmsRet = dbmsRet + line + '\n'
        if num_lines < chunk:
            break
    
    #   got it 
    print(dbmsRet)
    
    #   R e s u l t :
    #   Test no. 1
    #       Test no. 1
    #       Test no. 2    
    

    Asking about pandas - if you add

    import pandas as pd
    

    and change the end of the code to

        myList = []
        for line in lines:
            myList.append(line)
            dbmsRet = dbmsRet + line + '\n'
        if num_lines < chunk:
            break
    
    #   got it 
    df = pd.DataFrame(myList)
    print(df)
    print(type(df))
    
    #   The Result would be
    #                              0
    #  0                  Test no. 1
    #  1  \tTest no. 1\n\tTest no. 2
    #  <class 'pandas.core.frame.DataFrame'>