使用subprocess和xclip的Python脚本如果在bash中传送,则会挂起

时间:2017-06-14 19:50:25

标签: python shell subprocess piping xclip

我有一个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()))

该脚本按预期工作:{b}中回显PRINT_ME,可以粘贴PASTE_ME,并返回imediatly。

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

$ python clip.py|tee file.txt

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

如何解决这个问题?

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

我使用的是Python 3.4 感谢

1 个答案:

答案 0 :(得分:2)

这不是由于xclip的分支,而是由于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(或{3.}为Python 3.x)时重定向它或者你想要的任何其他流句柄。