我有一个 python 脚本,需要将一些值输出到 stdin 并将另一个字符串复制到剪贴板。我正在使用模块 subprocess 通过 xclip 执行 Popen 实用程序,如下所示:

# clip.py
import subprocess
from subprocess import Popen

print('PRINT_ME')
p1 = Popen(['xclip', '-selection', 'clipboard'], stdin=subprocess.PIPE)
p1.communicate(input=('PASTE_ME'.encode()))

该脚本按预期工作:PRINT_ME 在 bash 中回显,PASTE_ME 可用于粘贴,并立即返回。

当脚本输出通过管道传输到另一个命令时会出现问题。假设有人想使用 tee 重定向到一个文件和标准输入:
$ python clip.py|tee file.txt

该程序按预期工作但不返回,即 shell 不返回控制权。

这怎么能解决?

一些重要信息 : xclip 实用程序 fork 本身(以应对 X 上剪贴板的实现)维护可复制的字符串,当在 shell 中使用时它立即返回( fork 到后台)。 shell 似乎将 clip.pyxclip stdin/stdout 附加到 tee
如果使用 xclip -selection clipboard 找到 ps u 并杀死命令返回。

我正在使用 Python 3.4。
谢谢

最佳答案

这不是由于 xclip 的 fork ,而是由于 Python 处理 Popen.wait() (通过调用 communicate() 调用)的方式 - 从 Python 的角度来看 xclip (默认情况下是静默的)没有关闭它的流,所以它等待......这就是为什么一切除了 Python 在将其流传输到其他内容(在本例中为 p1.communicate())时移过您的 tee 行之外,它可以工作 - 它等待其所有文件句柄关闭...

你可以手动打开和关闭你的流,或者只配置 xclip 来过滤 STDIN 到 STDOUT 并让 Python 满意:

import subprocess

p1 = subprocess.Popen(['xclip', '-selection', 'clipboard', '-f'], stdin=subprocess.PIPE)
p1.communicate(input=('PASTE_ME'.encode()))
# etc.

没有测试它,但它应该工作。如果您不希望 xclip 打印到您当前的 STDOUT,只需在将 subprocess.Popen() 实例化为 None(或 Python 3.x 的 subprocess.DEVNULL)或您想要的任何其他流句柄时将其重定向。

关于如果在 bash 中进行管道传输,则使用子进程和 xclip 的 Python 脚本会挂起,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44553539/

10-13 05:08