subprocess.Popen简单代码不允许我执行cd(更改目录)

时间:2014-06-11 11:12:27

标签: python subprocess popen

我正在尝试使用Python脚本来更改目录,但是我收到了一个错误。

python代码:

import subprocess
p = subprocess.Popen(['cd', '~'], stdout=subprocess.PIPE)
output = p.communicate()
print output

我收到此错误:

File "test_sub.py", line 2, in <module>
p = subprocess.Popen(['cd', '~'], stdout=subprocess.PIPE)
File "/usr/lib/python2.7/subprocess.py", line 710, in __init__
errread, errwrite)
File "/usr/lib/python2.7/subprocess.py", line 1327, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory

错误意味着什么,我做错了什么,以及如何更改python子流程中的目录?

3 个答案:

答案 0 :(得分:8)

>>> Popen('cd ~', shell=True, stdout=PIPE).communicate()
(b'', None)

没有shell=True(模仿shell)

>>> Popen(['cd', '~'], stdout=PIPE).communicate()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.4/subprocess.py", line 858, in __init__
    restore_signals, start_new_session)
  File "/usr/lib/python3.4/subprocess.py", line 1456, in _execute_child
    raise child_exception_type(errno_num, err_msg)
FileNotFoundError: [Errno 2] No such file or directory: 'cd'
>>> 

除非您通过以下方式进行更改,否则无法更改目录:

import os
os.chdir(os.path.abspath(os.path.expanduser('~')))

所以问题不在于路径~不存在,而是cd在Python的模拟终端中不作为选项存在。直接传递给实际的shell会使cd起作用。但请注意,shell=True是一种风险,除非您需要,否则永远不要使用它 所以请改用os.chdir

工作方案:

import os, subprocess
os.chdir(os.path.abspath('/tmp/'))
print(subprocess.Popen(['ls', '-lah'], stdout=subprocess.PIPE).communicate()[0].decode('utf-8'))

导致:

[torxed@archie ~]$ python
Python 3.4.1 (default, May 19 2014, 17:23:49) 

>>> import os, subprocess
>>> os.chdir(os.path.abspath('/tmp/'))
>>> print(subprocess.Popen(['ls', '-lah'], stdout=subprocess.PIPE).communicate()[0].decode('utf-8'))

total 12K
drwxrwxrwt  9 root   root   220 Jun 11 12:08 .
drwxr-xr-x 19 root   root  4.0K May 28 08:03 ..
drwxrwxrwt  2 root   root    40 Jun 11 09:30 .font-unix
drwx------  2 torxed users   60 Jun 11 09:33 gpg-LBLcdd
drwxrwxrwt  2 root   root    40 Jun 11 09:30 .ICE-unix
drwx------  2 torxed users   80 Jun 11 09:34 .org.chromium.Chromium.LEqfXB
-rw-------  1 torxed users  153 Jun 11 09:34 serverauth.EHWB0LqCv6
drwxrwxrwt  2 root   root    40 Jun 11 09:30 .Test-unix
-r--r--r--  1 root   users   11 Jun 11 09:34 .X0-lock
drwxrwxrwt  2 root   root    60 Jun 11 09:34 .X11-unix
drwxrwxrwt  2 root   root    40 Jun 11 09:30 .XIM-unix

>>> 

请注意,我在~中启动了shell,并通过os.chdir将其更改为tmp并实际获得了我的tmp目录内容。

shell和命令的说明:

shell命令是内置于shell中的内容,而常规旧命令是您在/bin下可以找到的内容,例如:

[torxed@archie ~]$ ls /bin
2to3            2to3-2.7
7z              7za
...

其中7z是一个我可以实际执行的命令:

>>> from subprocess import *
>>> Popen(['7z'], stdout=PIPE).communicate()

(b'\n7-Zip [64] 9.20  Copyright (c) 1999-2010 Igor Pavlov  2010-11-18\np7zip Version 9.20 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,8 CPUs)\n

虽然例如cd是一个内置的shell命令,但在/bin下你找不到但在大多数&#34;终端&#34; (使用shell)因为它(如上所述)内置于您通常看到的shell中
但是因为Python会模拟一个shell ,所以只有一组内置且有效的命令,cd是其中之一但不能补偿你的内容使用os.chdir(...)执行完全相同的功能并影响整个程序。

答案 1 :(得分:1)

cd是shell的内置命令,它改变shell的环境以设置将运行的下一个命令的当前目录。它是常规程序。所以它不能被称为Popen的子进程。

更改python中当前目录的正确方法是:

import os
os.chdir(os.path.abspath(os.path.expanduser('~')))
#now the current directory is home of user

答案 2 :(得分:0)

您需要在

中包含所有路径
path = os.path.dirname('$0')
currentpath = os.path.abspath(path)
os.chdir(path)