os.system与命令行有何不同?

时间:2017-07-27 09:42:55

标签: python python-3.x command-line os.system pyzo

为什么我的python解释器中的os.system('命令')与终端的命令输出不同?

问题迅速解释:

我有

log4jdbc.dump.sql.addsemicolon=true
log4jdbc.dump.sql.maxlinelength=0
log4jdbc.trim.sql.extrablanklines=false

echo $CONFPATH
/home/claramart/Datamart/Parameter

为什么?

详细信息: 我想让我的环境$ CONFPATH。我使用的是python3.5和ubuntu16.04.2。

我可以从命令行执行此操作:

os.system('echo $CONFPATH')

0

这就是我想要的答案。

从命令行执行python命令也可以:

echo $CONFPATH
/home/claramart/Datamart/Parameter

问题是,我想从我的python解释器执行此操作,而不是从命令行执行。 从我的python解释器执行它不起作用(我正在使用Pyzo4.4.1):

python3 -c 'import os; print(os.environ["CONFPATH"])'
/home/claramart/Datamart/Parameter

我认为这严格来自我的解释器而不是python本身,因为命令行的python执行起作用。而且,我可以从我的python解释器获得$ PYTHONPATH,所以我猜它根本不检测所有环境变量。

为了避免这种情况,并且从命令行执行它,我想从我的python解释器执行命令行执行,但我的2个命令行执行都没有按照我想要的方式工作:

print(os.environ["CONFPATH"])
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/lib/python3.5/os.py", line 725, in __getitem__
    raise KeyError(key) from None
KeyError: 'CONFPATH'

和:

os.system('echo $CONFPATH')

0

再一次,在这两种情况下,它都适用于$ PYTHONPATH,所以我想它必须在某个时候通过我的解释器,因为我的问题特定于该变量$ CONFPATH。

为什么我的python解释器中的os.system(&#39; command&#39;)与终端的命令输出不同?

2 个答案:

答案 0 :(得分:2)

我认为你期待有一个环境。事实是,每个进程都有自己的环境,通常从其父进程继承。不幸的是,我没有在你的片段中看到足够的信息来告诉你如何传递这个特定的价值,但我们可以通过它们看看他们实际说的是什么。

echo $CONFPATH
/home/claramart/Datamart/Parameter

这显示了一个shell命令echo,证明shell可以扩展参数$CONFPATH。但是,它不会显示是来自shell还是环境变量。后来的片段确实证明了你确实有一个可以设置的环境。

os.system('echo $CONFPATH')

0

这是一个Python函数调用,反过来调用C库函数,这会导致生成一个新的shell并解释给定的命令。值得注意的是,这与你运行的任何外壳都不一样;它是一个新的/ bin / sh进程,它从调用的Python解释器继承环境。我们看到这个shell命令成功(退出值0)并将CONFPATH扩展为空,表明它是空的或未设置Python解释器的环境。

python3 -c 'import os; print(os.environ["CONFPATH"])'
/home/claramart/Datamart/Parameter

这是一个启动Python解释器的shell命令的示例,其命令行使其打印环境变量。它成功了,因为变量是从运行命令的shell继承的。

os.system("""python3 -c 'import os; print(os.environ["CONFPATH"]'""")
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib/python3.5/os.py", line 725, in __getitem__
    raise KeyError(key) from None
KeyError: 'CONFPATH'
256

这里有一个被另一个包裹着;从Python解释器开始,shell开始运行一个命令,该命令启动另一个应该打印CONFPATH环境变量的Python解释器。但是,这个内部Python代码失败,在其环境中未找到CONFPATH时引发了KeyError异常。这与shell的简单显示空值的行为形成对比。由于没有捕获到异常,因此打印了一个回溯,并且Python shell返回了一个错误代码,然后由子shell返回,最后由我们的外部Python解释器打印为256.

您已经显示了从两个不同的环境运行的命令:设置了CONFPATH的shell,以及不设置CONFPATH的Python解释器。 pstreeps fps -H可以帮助您可视化流程树,从而帮助您继承环境的位置。请注意,环境是从父进程复制的;在父母中更改它只会影响新孩子,而不影响现有孩子。

在Linux中,还可以在/ proc文件系统中找到环境。例如,tr \\0 \\n < /proc/$$/environ打印它运行的shell的环境(shell将$$扩展为自己的进程ID)。

当你从不同的环境中运行时,这种区别变得更加重要;例如,通过.profile.bashrc文件设置的任何内容都不会影响从cron运行的命令,与系统启动脚本类似。大多数程序按原样保留环境,但有些程序会产生特定的异常,例如setuid程序忽略LD_LIBRARY_PATH,或suenv重写环境。

答案 1 :(得分:1)

尝试从父shell导出 shell变量,即启动Python的shell:

$ CONFPATH=/home/claramart/Datamart/Parameter
$ echo $CONFPATH
/home/claramart/Datamart/Parameter
$ env | grep CONFPATH
$ python3 -c 'import os; print(os.environ["CONFPATH"])'
Traceback (most recent call last):
  File "", line 1, in 
  File "/usr/lib64/python3.5/os.py", line 725, in __getitem__
    raise KeyError(key) from None
KeyError: 'CONFPATH'
$ python3 -c 'import os; print(os.system("echo $CONFPATH"))'

0

# Try the same after exporting the variable
$ export CONFPATH
$ env | grep CONFPATH
CONFPATH=/home/claramart/Datamart/Parameter
$ python3 -c 'import os; print(os.environ["CONFPATH"])'
/home/claramart/Datamart/Parameter
$ python3 -c 'import os; print(os.system("echo $CONFPATH"))'
/home/claramart/Datamart/Parameter
0

默认情况下不会导出Shell变量,因此,在上面的export命令之前,父进程(终端的shell)实际上并不导出CONFPATH。如上所示,您的Python进程根本不应在其环境中定义CONFPATH

说过我很惊讶地看到在os.environ中查找环境变量显然对你有用,而os.system()却没有。两者都应该工作,或者两者都不应该工作,这取决于环境变量的可用性。也许这是使用Pyzo的怪癖,或者是你(或Pyzo)调用解释器的方式。