在Python中以相同进程执行BASH命令
我需要在使用 Python 2.6 导入 ibm_db_dbi
之前,先执行这个命令 . /home/db2v95/sqllib/db2profile
。
如果在进入 Python 之前执行这个命令是可以的:
baldurb@gigur:~$ . /home/db2v95/sqllib/db2profile
baldurb@gigur:~$ python
Python 2.6.4 (r264:75706, Dec 7 2009, 18:45:15)
[GCC 4.4.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import ibm_db_dbi
>>>
但是如果我在 Python 中用 os.system(". /home/db2v95/sqllib/db2profile")
或者 subprocess.Popen([". /home/db2v95/sqllib/db2profile"])
来执行,就会出错。我哪里做错了呢?
编辑:这是我收到的错误信息:
> Traceback (most recent call last):
> File "<file>.py", line 8, in
> <module>
> subprocess.Popen([". /home/db2v95/sqllib/db2profile"])
> File
> "/usr/lib/python2.6/subprocess.py",
> line 621, in __init__
> errread, errwrite) File "/usr/lib/python2.6/subprocess.py",
> line 1126, in _execute_child
> raise child_exception OSError: [Errno 2] No such file or directory
4 个回答
也许你需要的是 os.popen
这个东西(更好的是,试试 popen[2-4]
的变种)?下面是个例子:
import os
p = os.popen(". /home/b2v95/sqllib/db2profile")
p.close() # this will wait for the command to finish
import ibm_db_dbi
补充:我看到你的错误信息显示 No such file or directory
。试着去掉那个点,像这样运行:
os.popen("/home/b2v95/sqllib/db2profile")
如果这样还不行,可能跟你的环境有关。也许你是在一个受限制的环境中运行 Python?
我不太清楚你在使用什么操作系统和哪个版本的DB2。较新的版本(至少是9.5及以上,9.0或9.1我就不太确定了)是通过把db2clp设置为**$$**
来工作的。因为DB2通常是一个LUW(Linux、Unix、Windows),所以在Linux或Unix上也可能能用。不过,在AIX系统上,我需要运行一个配置脚本才能连接到正确的数据库实例。我还没有仔细研究这个脚本具体是干什么的。
你在调用一个 '.' 的命令。这个命令的意思是“在当前进程中执行这个 shell 文件”。但是你不能在 Python 进程中执行 shell 文件,因为 Python 不是一个 shell 脚本解释器。
/home/b2v95/sqllib/db2profile
这个文件可能会设置一些 shell 环境变量。如果你用 system()
函数去读取它,那么这些变量只会在执行这个 shell 的环境中改变,而在调用这个 shell 的进程(也就是你的脚本)中是看不到的。
你只能在启动 Python 脚本之前加载这个文件——你可以写一个 shell 包装脚本,先执行 . /home/b2v95/sqllib/db2profile
,然后再执行你的 Python 脚本。
另一种方法是查看 db2profile
文件的内容。如果里面只有 NAME=value
这样的行,你可以在你的 Python 脚本中解析这些内容,并用获取到的数据更新 os.environ
。如果这个脚本做了更多的事情(比如调用其他东西来获取值),你可以把整个脚本用 Python 重新实现一遍。
更新 一个想法:把这个脚本读入 Python 中,然后用 Popen 将它传给 shell,脚本执行完后再在同一个 shell 中写 env
命令并读取输出。这样你就能获取到在 shell 中定义的所有变量。现在你可以读取这些变量了。
大概是这样的:
shell = subprocess.Popen(["sh"], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
script = open("/home/db2v95/sqllib/db2profile", "r").read()
shell.stdin.write(script + "\n")
shell.stdin.write("env\n")
shell.stdin.close()
for line in shell.stdout:
name, value = line.strip().split("=", 1)
os.environ[name] = value