java調用python的慘痛史(無法獲取環境變量)


環境:java,was,python2.6,紅帽linux,oracle,python用cx_Oracle
        事情是這樣的,有個需求,需要對數據庫進行處理,簡單說就是把數據取出來,用python使用外部傳參做一個處理,再寫回到數據庫。如果使用java直接搞的話需要繞很大一個圈,比較麻煩,用python的話就很簡單了,於是就有了下面的故事,希望和我遇到同樣問題的同學能對你們有一些幫助,少繞一些圈子,java和python功能開發都很順利,於是到了java調用python環節


大概把需要用到的功能寫兩個腳本,一個是用於連接數據庫的,一個是用來實現功能的,方便后面說明
dbconn.py 這個用來連接數據庫

#!/usr/bin/python
# coding: UTF-8

import cx_Oracle

def ora_conn():
  user_name = 'user'
  passwd = 'pass'
  host = 'localhost/orcl'
  conn = cx_Oracle()
  return conn

case.py 這個用來加工數據

'''
接收傳入參數
使用傳入參數作為where條件到oracle中進行查找
對數據進行處理
寫回到oracle
'''
#!/usr/bin/python
# coding: UTF-8

import os
import sys

#嘗試獲取環境變量my_home
my_home = os.getenv('my_home')
if not my_home:
  my_home = '/home/user_name'

#cx_Oracle腳本是放在pypk目錄里的,因此需要增加這個地方
sys.path.append('%s/pypk' %my_home) 

import dbconn

#接收參數,為了防止后面因為手誤將此變量變更這里用global聲明下全局,可有可無
global out_into
out_into = sys.argv[1]

#獲取數據庫數據
def get_data():
  print 'get data'
  conn = dbconn.ora_conn()
  conn_cur = conn.cursor()
  sql = 'select col1,col2 from tablename where col1 = %r' %out_into
  data_values = conn_cur.execute(sql)
  result = list(data_values)
  conn_cur.close()
  conn.close()
  return result

#處理,為了方便,假設就是在col1前面加a和col2前面加b,然后拼在一起用;分隔
def manage_data(values):
  print 'manage data'
  col1 = 'a' + str(values[0])
  col2 = 'b' + str(values[1])
  col_return = col1 + ';' + col2
  return col_return

#寫入數據庫d
def into_data(into_values):
  print 'insert into data'
  conn = dbconn.ora_conn()
  conn_cur = conn.cursor()
  sql = 'insert into result_table(col) values(%r)' %into_values
  conn_cur.execute(sql)
  conn.commit()
  conn_cur.close()
  conn.close()

def main():
  print 'run start'
  datas = get_data()
  for line in datas:
    ok_values = manage_data(line)
    into_data(ok_values)

if __name__ == '__main__':
  main()
  exit()

 

因為不知道java調用效果怎樣,先寫了個簡單的python腳本用java調用測試了下

test.py 這個只是用來測試功能,所以只有一行代碼

print 'hello'

測試成功,這里因為這邊沒有環境,就不截圖了,大家湊合看吧。又加入兩行,測試了一下傳參

test.py

print 'hello'
a = sys.argv[1]
print a

 

一樣成功了,信心滿滿的上正式腳本來測試,正常打印了腳本中的內容

run start
get data
manage data
insert into data

去數據庫里面查,結果目標表result_table沒有數據。我擦,這什么鬼,沒報錯也沒有處理,完全沒有頭緒,嘗試加上try看看有沒有什么幫助。於是case.py的main函數就變成了下面這樣

def main():
  print 'run start'
  try:
    datas = get_data()
    for line in datas:
      ok_values = manage_data(line)
      into_data(ok_values)
  except Exception, e:
    print e

 

       這次果然有結果了,cx_Oracle連接失敗,缺少libclntsh.so.11.1,這里着重說明下,網上都是win調用cx_Oracle的,需要拷貝什么dll,這個在linux中是沒用的,而且就算是win也不是像上面說的那樣把一堆dll拷貝到腳本當前目錄里面,這樣只是治標不治本。
正確的方法是加三個環境變量

export ORACLE_HOME=oracle_install_path #第一個當然是ORACLE_HOME
export PATH=$PATH:$ORACLE_HOME/bin #第二個是bin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME/lib #第三個是lib

我不想留坑,建議這三個變量加到~/.bashrc里面,不過這個並沒有解決根本問題,后面會說明,請各位繼續往下看


        加入環境變量以后又執行了下,報錯connect to Oracle Database,尼瑪犬加上了啊,於是在本地linux服務器執行了下,結果。。。。。。正常執行,完全問題,這次真是見鬼了啊。某楠說的好,真相只有一個,特么就不信了,我倒要看看是出什么問題了,根據以往經驗,環境變量加失敗的話可能是使用用戶和加環境變量的用戶不一致,於是在case.py里面加上一段

import getpass
now_user = getpass.getuser() #用來獲取當前操作用戶
print now_user

結果是root,對啊,是root啊,而且我也是SB了,.bashrc這個不是應該全局的么,就是全部用戶通用的環境變量啊。算了,死馬當活馬醫,倒要看看環境變量里都是什么玩意,在case.py里面再加一行

os.system('env') #調用linux的外部命令,查看全部環境變量

 

        然后,意外出現了,打印出來的環境變量里面根本就沒有加入的三個環境變量,而且大部分都不是linux里面的環境變量,好多都是was用的,難道是was有自己的環境變量么,問了下同事,果然坑啊,真的有自己的環境變量配置。這下問題找到了,那么解決辦法就是把這三個加到was自有的環境變量里面就好了嘛,於是。。。。。。在was里加入了ORACLE_HOME、PATH、LD_LIBRARY_PATH這三個環境變量。
        重新測試下,尼瑪剛才加入的居然不在里面,這就尷尬了,怎么辦。。。怎么辦。。。在分針從12繞到11的時候,終於,辦法有了,把環境變量作為外部命令加進去不就行了,繼續在case.py中加入三行

os.system(export ORACLE_HOME=oracle_install_path)
os.system(export PATH=$PATH:$ORACLE_HOME/bin)
os.system(export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME/lib)

 

        這時候我都快成福爾摩斯了,感覺已經超越某楠了有木有,但是事實仍然給了我當頭一棒,失敗了,打印出來的環境變量里這三個依然不存在的,原因是這樣加入的環境變量不會直接有效的,需要注銷才可以生效,簡直崩潰了,然后分針又默默的從12走到了11。突然靈感一現,如果用python自有的加環境變量的方法能不能繞過注銷這個步驟呢,說弄就弄,於是將case.py中的

os.system(export ORACLE_HOME=oracle_install_path)
os.system(export PATH=$PATH:$ORACLE_HOME/bin)
os.system(export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME/lib)

替換成下面的

oracle_home_env = [['ORACLE_HOME','oracle_install_path'],['PATH','$PATH:$ORACLE_HOME/bin'],['LD_LIBRARY_PATH','$LD_LIBRARY_PATH:$ORACLE_HOME/lib']]
for env_line in oracle_home_env:
  os.environ[env_line[0]] = env_line[1]

好吧,我承認,這個辦法不是我想出來的,能相出這種加環境變量方法的人真是大神啊


        繼續我們的故事,然后,奇跡出現了,這三個環境變量終於在打印的結果中出現了,但是依然報錯連接不上數據庫,不過這就好辦了,既然這個環境變量指向的linux,那只要用linux的方法調用腳本就好了嘛。說弄就弄,新加了一個腳本,用來調用case.py,只有幾行

call_script.py 用來使用外部命令調用case.py

#!/usr/bin/python
# coding: UTF-8

import os

out_into = sys.argv[1]

my_home = os.getenv('my_home')
if not my_home:
  my_home = '/home/user_name'

os.system('python %s/case.py %s' %(my_home,out_into))

到這里故事就結束了,不過就像大部分劇本一樣,總要有彩蛋嘛哈哈


        以為這樣就結束了么?當然不是,有沒有看到my_home,這個也是一個環境變量!這里沒有報錯的原因是因為在下面加入了一個if,如果沒有獲取到的話默認/home/user_name,但是路徑換了呢?這一路升級的,感覺小棍子都能升級到金箍棒了,這點小事還搞不定么,好了,不說了,我要去吃點什么慶祝了。


春節了,一年了,終於等到這一天了,能看到這個文也算是緣分,在這里就祝大家在新的一年里 多多賺錢、少一些坑、身體健健康康、立的flag都能實現!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM