Question

I'm coding a webservice on python that uses an Oracle database. I have cx_Oracle installed and working but I'm having some problems when I run my python code as CGI using Apache.

For example the following code works perfectly at the command line:

#!/usr/bin/python 
import os 
import cx_Oracle 
import defs as df 

os.putenv('ORACLE_HOME', '/oracledb/10.2.0/') 
os.putenv('LD_LIBRARY_PATH', '/oracledb/10.2.0/lib') 

con = cx_Oracle.Connection(df.DB_USER, df.DB_PASS, df.DB_SID) 
print con

But when I run it as CGI I get a "cx_Oracle.InterfaceError: Unable to acquire Oracle environment handle" at the apache error log.

I searched the Net and everybody says that I have to set the ORACLE_HOME and LD_LIBRARY_PATH environment variables. Somehow the CGI script cannot access this environment variables even when I define them using os.putenv as you can see at the code.

What I'm I doing wrong? Thanks!

Was it helpful?

Solution 7

I've managed to solve the problem.

Somehow the user and group that apache was using didn't have access to the environment variables. I solved the problem by changing the user and group that apache was using to a user that I was certain to have access to this variables.

It's strange (and frustrating) that it's so difficult to set this variables using Python.

Thanks to everyone that answered my question!

OTHER TIPS

This is working for me:

os.putenv('ORACLE_HOME', '/oracle/client/v10.2.0.3-64bit')
os.putenv('LD_LIBRARY_PATH', '/oracle/client/v10.2.0.3-64bit/lib')
os.environ['ORACLE_HOME'] = '/oracle/client/v10.2.0.3-64bit'
os.environ['LD_LIBRARY_PATH'] = '/oracle/client/v10.2.0.3-64bit/lib'

Mind that first putenv, then update environ.

You need this:

os.environ['ORACLE_HOME'] = '/oracledb/10.2.0/'
os.environ['LD_LIBRARY_PATH'] = '/oracledb/10.2.0/lib'

instead of using os.putenv() because os.putenv() doesn't update os.environ, which cx_Oracle is presumably looking at.

Documentation: Miscellaneous operating system interfaces says: "Note: Calling putenv() directly does not change os.environ, so it’s better to modify os.environ."

Don't forget adding env module for apache:

a2enmod env

in .htaccess or apache configuration:

SetEnv LD_LIBRARY_PATH /oracle_lib_path

in /etc/apache2/envvars doesn't work

You can eliminate the problem altogether if you eliminate the need to set the environment variables. Here's a note on how to do this by installing the Oracle Instant Client on your box.

installing Oracle Instantclient on Linux without setting environment variables?

From just a short google on the problem, it could be that your problem is related to the the ending / in ORACLE_HOME.
Try removing it (and using also suggestion from Richie) and see if it works.

You could use a shell script to implement the CGI, set the environment variables in the shell script and call the python script from the shell script.

Setting environment variables from within python seems to be a tricky thing, especially when you are dealing with how libraries are loaded...

The actual question why the questioner's code did not work has not yet been answered.

The answer is that the environment variable LD_LIBRARY_PATH is only evaluated when an application is started (in this case the Python interpreter). When Python has started, it is already too late to mess with this variable; and it doesn't matter at all whether you set it using os.environ or os.putenv (but generally the former should be used).

The solution is to set the LD_LIBRARY_PATH environment variable in a wrapper script that starts the Python script, or to start Apache with that environment variable already set. On OpenSUSE, you can do the latter by setting LD_LIBRARY_PATH in /etc/sysconfig/apache2, for instance.

By the way, the same problem exists when using mod_wsgi instead of a CGI script. See the section "Unable To Find Python Shared Library" on the mod_wsgi Installation Issues page.

Are your statements out of order?

#!/usr/bin/python 
import os 
os.putenv('ORACLE_HOME', '/oracledb/10.2.0/') 
os.putenv('LD_LIBRARY_PATH', '/oracledb/10.2.0/lib') 

import cx_Oracle 
import defs as df 

con = cx_Oracle.Connection(df.DB_USER, df.DB_PASS, df.DB_SID) 
print con
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top