【问题标题】:No such file or Directory Error with subprocess.call in PythonPython中的subprocess.call没有这样的文件或目录错误
【发布时间】:2017-07-24 15:23:13
【问题描述】:

一般来说,我尝试使用 Bash 从命令行而不是 Python 进行读取,这样我就有了制表符补全功能。我想以最简单的方式做到这一点。但是,我无法让以下代码正常工作,我想了解导致问题的原因。

Python 脚本:

from subprocess import call
call(['read', '-ep', 'Path:', 'temporaryPath'])
print temporaryPath

错误回溯:

Traceback (most recent call last):
  File "tmp.py", line 2, in <module>
    call(['read', '-ep', 'Path:', 'temporaryPath'])
  File "/usr/lib64/python2.6/subprocess.py", line 478, in call
    p = Popen(*popenargs, **kwargs)
  File "/usr/lib64/python2.6/subprocess.py", line 642, in __init__
    errread, errwrite)
  File "/usr/lib64/python2.6/subprocess.py", line 1238, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

【问题讨论】:

  • read 是内置的 bash,而不是二进制文件。

标签: python bash popen tab-completion


【解决方案1】:

您正在尝试调用 read,这是一个内置的 shell:

$ type read
read is a shell builtin

而且这个特殊的内置 shell 没有等效的程序:

$ which read
$ 

因此,根据strace,Python 将无法在您的PATH 环境变量中找到它:

[pid 17266] execve("/usr/local/bin/read", ["read", "-ep", "Path:", "temporaryPath"], [/* 70 vars */]) = -1 ENOENT (No such file or directory)
[pid 17266] execve("/usr/bin/read", ["read", "-ep", "Path:", "temporaryPath"], [/* 70 vars */]) = -1 ENOENT (No such file or directory)
[pid 17266] execve("/bin/read", ["read", "-ep", "Path:", "temporaryPath"], [/* 70 vars */]) = -1 ENOENT (No such file or directory)
[pid 17266] execve("/usr/local/games/read", ["read", "-ep", "Path:", "temporaryPath"], [/* 70 vars */]) = -1 ENOENT (No such file or directory)
[pid 17266] execve("/usr/games/read", ["read", "-ep", "Path:", "temporaryPath"], [/* 70 vars */]) = -1 ENOENT (No such file or directory)
[…]
[pid 17266] write(4, "OSError:", 8 <unfinished ...>

但如果你明确要求 Python 使用 shell 来执行你的命令,shell 本身将能够运行其内置的 read

$ python3
Python 3.5.3 (default, Jan 19 2017, 14:11:04) 
[GCC 6.3.0 20170118] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> subprocess.call('read', shell=True)
/bin/sh: 1: read: arg count
2
>>> subprocess.call('read foo', shell=True)
hello world
0

您现在遇到了一个新问题:内置的 shell read 将读取的值存储为一个 shell 变量,当调用 subprocess.call 后,shell 将立即死亡,该变量将消失。

哦,在read shell 内置你也没有完成。如果您想以交互方式向用户询问某些内容,或者如果不需要交互,您可能应该只使用input,只需使用argparse 来解析用户作为命令行参数提供的内容,这样用户就会有一些键入参数时的 shell 完成,通常不是在标志上,因为用户 shell 不知道它们,而是在路径上。

【讨论】:

  • 感谢您向我展示 argparse,它看起来是一种非常强大的方式来完成我想要的。另外,我现在明白为什么调用需要shell=True,但为什么以下不起作用? call('read -ep \"Path: \" temporaryPath; export temporaryPath', shell=True)
  • export 不允许你修改调用进程的环境。没有任何东西可以让您修改调用过程的环境。但是您仍然可以echo $temporaryPath 并从进程标准输出中获取值(不要这样做,最好使用input,甚至更好使用argparse)。
  • 啊,现在看起来很明显。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-12
  • 2022-10-21
  • 2021-10-31
  • 1970-01-01
  • 2020-03-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多