【问题标题】:Execute a BASH command in Python-- in the same process在 Python 中执行 BASH 命令——在同一进程中
【发布时间】:2010-05-18 15:57:43
【问题描述】:

我需要先执行命令. /home/db2v95/sqllib/db2profile,然后才能在 Python 2.6 中执行import ibm_db_dbi

在我进入 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

【问题讨论】:

  • 总猜测,但似乎脚本实际上在环境中设置了一些东西,这可能无法通过执行子进程来工作。
  • @abyx: 但这与给定的问题无关,即使它是真的

标签: python bash db2 subprocess


【解决方案1】:

您正在调用“。”外壳命令。该命令的意思是“在当前进程中执行这个 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,脚本后将env命令写入同一个shell并读取输出。这样,您将获得 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

【讨论】:

  • 啊,好点——db2profile 确实设置了shell 环境变量。不幸的是,我不能使用 shell 包装器调用 python 脚本(由于项目的性质),db2profile 很长,并且包含一些中等复杂的函数和(你猜对了)环境变量。我将如何在 Python 中运行整个文件?
  • 即是否可以在 Python 中运行具有大量赋值、环境变量和函数的 BASH 脚本?还是我必须用 Python 重写整个代码?
  • 我知道如何做到这一点:请参阅我帖子的更新。
  • Odd... 它输出:"""Traceback(最近一次调用最后一次):文件“.py”,第 14 行,在 shell = subprocess.Popen([" sh"], stdin=subprocess.pipe, stdout=subprocess.pipe) AttributeError: 'module' 对象没有属性 'pipe'"""
  • 那是我的错误(常量被命名为 'PIPE' 而不是 'pipe'),已经修复了。
【解决方案2】:

你需要做的:

subprocess.Popen(['.', '/home/db2v95/sqllib/db2profile'], shell=True)

【讨论】:

  • 这可能“有效”(不会引发任何异常),但很可能不会达到预期的效果。由于文件是“来源”的,它可能会设置一些环境变量。这些变量只会在 Popen 启动的 shell 中设置,在 Python 脚本调用中不可见。
  • 这将导致: Traceback(最近一次调用最后一次):文件“gagnagrunnur.py”,第 14 行,在 中 import ibm_db_dbi 文件“/usr/local/lib/python2.6/dist -packages/ibm_db_dbi.py”,第 26 行,在 中 import ibm_db ImportError: libdb2.so.1: cannot open shared object file: No such file or directory 我想强调这可以使用命令行。跨度>
  • @baldur:你在等待进程终止吗?
【解决方案3】:

不确定您正在使用什么操作系统以及您正在使用什么 DB2 版本。较新的版本(至少 9.5 及更高版本,不确定 9.0 或 9.1)通过将 db2clp 设置为 **$$** 来工作。由于 DB2 通常是 LUW,因此它也可以在 linux/unix 下工作。但是,在 AIX 下,我需要运行配置文件脚本以连接到正确的数据库实例。没有过多检查该脚本的作用。

【讨论】:

    【解决方案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 被监禁/chroot?

    【讨论】:

    • 哦,该死。没有看到大红色警告。对此感到抱歉。
    • 不仅不推荐使用 - 从未打算以这种方式使用(打开管道并忽略输出)。如果您只想运行 shell 命令而不与它通信,请使用 os.system()subprocess.call(),而不是 os.popen()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-20
    相关资源
    最近更新 更多