【问题标题】:subprocess.Popen simple code does not allow me to perform a cd (change directory)subprocess.Popen 简单代码不允许我执行 cd (更改目录)
【发布时间】:2014-08-01 10:12:15
【问题描述】:

我正在尝试使用 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 子进程中更改目录?

【问题讨论】:

  • 用完整路径试试?
  • @Ashalynd 此错误消息是 Python2 中的一般错误消息,未指定 cd 不存在。

标签: python subprocess popen


【解决方案1】:
>>> Popen('cd ~', shell=True, stdout=PIPE).communicate()
(b'', None)

没有shell=True (在shell中运行命令,在默认为/bin/shPOSIX上)

>>> 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 作为选项不存在,除非您的命令在支持它的shell 中运行。直接传递给实际的 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 下找不到但在大多数“终端”(使用 shell)中仍然有效,因为它(如前所述)内置在 shell 中你通常会看到。

但是因为 Python 默认不会在 shell 中执行命令,所以您或多或少不得不依赖使用 os.chdir(...) 或将命令包装在 /bin/sh -c "cd ..." 或类似的东西中。

【讨论】:

  • 我真的不知道 shell=True 的含义,但是如果我添加错误消失了,但是我看不到任何输出,即使我将“cd”更改为一个简单的'ls'。我需要使用 ['command1', 'command2'] 因为命令来自变量。另外,当然,我需要查看在 python 程序上使用这些命令的结果。谢谢,对不起,我只是一个初学者。
  • @Haddex cd 没有任何输出,它只是将您从一个位置移动到另一个位置。如果您希望看到[user@machine ~],您就误解了shell 的工作原理。 cd 也是一个 shell 命令,而不是 Linux 命令(linux“命令”是位于 /bin 下的任何东西,而 shell 命令是内置在 shell 中的东西)。
  • @Haddex 希望我的编辑能够阐明cd 是什么以及您如何知道可以通过使用ls /bin 来执行哪些命令。
  • 您可以将cwd 参数传递给子进程,而不是父进程中的os.chdir()
  • 这个答案不正确。 cd 从 python 启动 shell 工作正常。问题是它更改了shell本身的目录,而不是父进程中的目录,因此它不适用于在调用进程中更改目录。
【解决方案2】:

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

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

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

【讨论】:

  • @Torxed 很抱歉,但 the version 我看到它为什么不起作用很神秘
  • 很公平 :) 在我深入了解我真正想说的话之前,我可以先用我的语言有点“圆” :)
  • 嗯,它“可以”通过给shell=True来调用,但它只会改变shell本身的状态。
【解决方案3】:

您需要包含所有路径

path = os.path.dirname('$0')
currentpath = os.path.abspath(path)
os.chdir(path)

【讨论】:

  • (这篇文章似乎没有为问题提供quality answer。请编辑您的答案,或者将其作为对问题的评论发布)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-23
  • 2017-06-19
相关资源
最近更新 更多