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

2022-01-18 00:00:00 python subprocess popen

问题描述

我正在尝试使用 Python 脚本更改目录,但出现错误.

I'm trying to use a Python script to change directory, but I am getting an error.

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 子进程中更改目录?

What does the error mean, what am I doing wrong, and how do I change directory in a python subprocess?


解决方案

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

不带 shell=True (在 shell 中运行命令,在默认为 /bin/sh 的 POSIX 上)

Without shell=True (which, runs the command in shell, on POSIX that defaults to /bin/sh)

>>> 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'
>>> 

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

You can't change directory unless you do it via:

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

所以问题不在于路径 ~ 不存在,而是 cd 作为选项不存在,除非您的命令在 shell 中运行支持它.直接传递给实际的 shell 使 cd 工作.但请注意,shell=True 是有风险的,除非您需要,否则切勿使用它..
所以请改用 os.chdir.

So the problem isn't that the path ~ doesn't exist, but rather cd doesn't exist as an option unless your command is run in a shell that supports it. Passing directly to an actual shell makes cd work. But note that shell=True is a risk, never use it unless you need to..
So use os.chdir instead.

一个工作场景:

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 目录内容.

Note that i started the shell in ~ and via os.chdir changed it to tmp and actually got my tmp directory content.

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

A shell-command is something that's built into the shell while a regular old command is something you'll find under /bin, for instance:

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

7z 是我可以实际执行的命令:

Where 7z is a command i can actually execute:

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

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

例如,虽然 cd 是一个内置的 shell 命令,但在 /bin 下找不到该命令,但在大多数终端"中都可以使用.(使用外壳)因为它(如前所述)内置于您通常看到的外壳中.

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

While for instance cd is a built in shell command, something that you will not find under /bin but works anyway in most "terminals" (using a shell) because it's (as mentioned), built into the shell you normally see.

But because Python will by default not execute the command in a shell you more or less have to rely on using os.chdir(...) or wrap your command in /bin/sh -c "cd ..." or something similar.

相关文章