2017-07-27 168 views
0

为什么我的Python解释器的os.system('command')与终端的命令没有相同的输出?os.system与命令行有什么不同?

问连忙解释道:

echo $CONFPATH 
/home/claramart/Datamart/Parameter 

os.system('echo $CONFPATH') 

0 

这是为什么?

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

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

echo $CONFPATH 
/home/claramart/Datamart/Parameter 

这就是我想要的答案。

执行它作为命令行Python的命令也适用:

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

的事情是,我想从我的Python解释器执行此,而不是命令行。 从我的Python解释器执行它不工作(我使用Pyzo4.4.1):

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' 

我想这是严格从我的解释,而不是来自Python本身作为蟒蛇执行命令行工作。此外,我可以从我的python解释器中获得$ PYTHONPATH,所以我想它根本不检测所有的环境变量。

为了避免这一点,从命令行执行它的工作,我想这样做,因为从我的Python解释器的命令行执行,但没有我的2所命令行执行的工作,我希望的方式来:

os.system('echo $CONFPATH') 

0 

和:

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 

再次在这两种情况下,它的工作为$ PYTHONPATH,所以我想它必须在某个时候通过我的翻译,因为我的问题是特定于变量$ CONFPATH。

为什么我的Python解释器的os.system('command')与终端的命令没有相同的输出?

+0

在任何默认shell中运行该命令,然后您将获得环境。所以:'os.system(“”“/ usr/bin/bash -c python3 -c'import os; print(os.environ [”CONFPATH“]'”“”)' - 可能没有引用那个对或得到正确的路径bash,但希望你能得到想法 – barny

+0

我明白了,但是我之前没有用过这个和'os.system(“”“/ bin/bash -c python3 -c'import os; print(os .environ [“CONFPATH”]'“”“)'开始一个dos似乎没有结束的进程,就像它被卡住了一样。也许我做错了吗? – Ashargin

+0

”执行它从我的python解释器不起作用Pyzo4.4.1)“我认为Pyzo解释器运行在不同的环境中,具有不同的环境变量,它是否在标准解释器中工作? – Goyo

回答

2

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

echo $CONFPATH 
/home/claramart/Datamart/Parameter 

这表明表明shell可能扩展参数$CONFPATH shell命令echo。但是,它并不显示它是来自shell还是环境变量。不过,后面的代码片段确实表明你确实有一个设置它的环境。

os.system('echo $CONFPATH') 

0 

这里是一个Python函数调用,反过来调用C库函数,这将导致一个新的外壳将被启动,并解释给定的命令。值得注意的是,这与你所运行的不一样。它是一个新的/ 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,以及一个其中没有的Python解释器。 pstree,ps fps -H可能会帮助您可视化过程树,从而可以看到环境从何处继承。请注意,环境是从父进程复制的;改变它在父母只会影响新的孩子,而不是现有的。

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

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

+0

令人惊叹的答案。 – Ashargin

1

尝试出口 shell变量从父壳,即其中开始的Python壳:

 
$ 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 

壳牌变量不是默认出口所以,上面的export命令之前,CONFPATH是实际上并没有被父进程导出(你的终端的shell)。如上所示,您的Python进程在其环境中根本不应该定义CONFPATH

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

相关问题