FastScripts MacOSX app:调用子处理的Python脚本时出现奇怪的stdin行为

时间:2015-05-09 06:31:35

标签: python macos shell keyboard-shortcuts stdin

概要。为什么FastScripts application执行以下操作,是否有目的,我或FastScripts开发人员能否以某种方式修复/更改行为而不执行此操作? (我发现FastScripts是一个很棒的应用程序。我正在运行MacOS 10.9.5。)

详情。

FastScripts 2.6.8似乎将其运行的当前脚本的内容复制到stdin,用于在所述脚本中运行的任何子进程,如下面的命令行会话所示。这不仅非常奇怪,在开发由FastScripts指令触发的软件时会引起很大的混淆。

我没有用非Python脚本测试过类似的行为,但是我写的多个独立的Python程序都表现得一样。我将通过电子邮件将这个问题的链接发送给FastScripts开发人员/技术支持。

以下演示了正确运行的脚本:

$ cat test_subprocess_stdin.py 
#!/usr/bin/env python
import subprocess
cmd1 = '/tmp/reprint_stdin.py            >/tmp/cmd1out.txt'
cmd2 = '/tmp/reprint_stdin.py </dev/null >/tmp/cmd2out.txt'
subprocess.Popen(cmd1, shell=True)
subprocess.Popen(cmd2, shell=True)
$ cat /tmp/reprint_stdin.py 
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
# from http://stackoverflow.com/a/17735803/605356
stdin_content_present = not sys.stdin.isatty()
if stdin_content_present:
    for line in sys.stdin:
        sys.stdout.write('stdin: ' + line)
$ ./test_subprocess_stdin.py 
$ cat /tmp/cmd1out.txt
$ cat /tmp/cmd2out.txt
$

然而,从FastScripts运行上述脚本时会发生奇怪的事情:

$ # <now running test_subprocess_stdin.py from FastScripts keyboard shortcut>
$ 
$ cat /tmp/cmd1out.txt 
stdin: #!/usr/bin/env python
stdin: import subprocess
stdin: cmd1 = '/tmp/reprint_stdin.py            >/tmp/cmd1out.txt'
stdin: cmd2 = '/tmp/reprint_stdin.py </dev/null >/tmp/cmd2out.txt'
stdin: subprocess.Popen(cmd1, shell=True)
stdin: subprocess.Popen(cmd2, shell=True)
$ cat /tmp/cmd2out.txt 
$ 
$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.9.5
BuildVersion:   13F1077
$ 

请注意,调用os.system()代替subprocess.Popen()会导致相同的异常行为。

出于某种原因,FastScripts和FastScripts似乎将正在运行的脚本的内容(在上面的例子中为test_subprocess_stdin.py)指向任何(子)脚本的stdin。在顶级脚本/程序中调用。 (</dev/null指示被调用的下标忽略stdin。)这很奇怪,因此,我需要花费大量的开发和调试时间来发现为什么我的FastScript调用程序正在破坏。

1 个答案:

答案 0 :(得分:1)

感谢您提出这个有趣的问题。我已经下载并确认了您看到的相同行为,并且我正在尝试理解它。

FastScripts运行shell脚本的方式是从#解释! (shebang)在脚本行中运行工具的名称,然后简单地运行该工具,提供脚本文件的内容作为正在运行的工具的标准输入。例如,在您的示例中,它将运行:

/ usr / bin / env python

以文件内容作为标准输入。

据我所知,这是一种非常传统的方法来调用shell工具来运行任意基于脚本的命令。那么为什么FastScripts的行为与例如从命令行运行该工具?我不知道。

显然有充分证据表明,子进程确实继承了他们的父进程,例如: stdin(https://unix.stackexchange.com/questions/58252/what-sets-a-childs-stderr-stdout-and-stdin),所以当env运行python并且python运行子进程调用时,标准输入应该保持活动状态并不神秘。

我想到的问题是,在直接从命令行运行脚本的情况下会发生什么?我不知道shell脚本执行的标准实现是否做了一些特殊的事情来防止将stdin传播到脚本本身。我不得不考虑这个。