如果在bash中通过管道传输,则使用子流程和xclip的Python脚本将挂起

如果在bash中通过管道传输,则使用子流程和xclip的Python脚本将挂起,python,shell,subprocess,piping,xclip,Python,Shell,Subprocess,Piping,Xclip,我有一个python脚本,需要将一些值输出到stdin并将另一个字符串复制到剪贴板。我使用模块子流程通过Popen执行xclip实用程序,如下所示: # clip.py import subprocess from subprocess import Popen print('PRINT_ME') p1 = Popen(['xclip', '-selection', 'clipboard'], stdin=subprocess.PIPE) p1.communicate(input=('PAST

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

# 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\u ME
在bash中回响,
PASTE\u ME
可用于粘贴,并立即返回

当脚本输出通过管道传输到另一个命令时,会出现问题。假设要使用
tee
重定向到文件和stdin:

$ python clip.py|tee file.txt
程序按预期工作,但不返回,即shell不返回控制权

这个问题怎么解决

一些重要信息
xclip
实用程序自身分叉保持字符串可复制,在shell中使用时立即返回(分叉到后台)。外壳似乎同时将
clip.py
xclip
stdin/stdout连接到
tee

如果使用
ps u
找到
xclip-选择剪贴板
,并将其终止,则命令返回

我正在使用Python 3.4。

感谢

这不是由于
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
打印到当前标准,请不要在实例化
subprocess.Popen()
时将其重定向到
None
(或Python 3.x的
subprocess.DEVNULL
)或任何其他您想要的流句柄。

谢谢您的回答,这两种方法都很好!我测试了各种修改,发现有趣的是,在执行
p1.communicate
(在原始缺陷代码中)之后的任何代码,程序都会停止退出。从提出的两种解决方案来看,哪一种更具“pythonic”性且无副作用?你是对的,我表达得很糟糕-Popen为xclip的STDOUT打开了一个FH(并将其与当前STDOUT绑定),而且由于
xclip
从不关闭它一直等待的流,因此它可以干净地退出子流程。至于Pythonic——这是一个虚幻的术语,对不同的人来说意味着不同的事情,但大多数人倾向于认为接吻法是Pythonic的缩影——因此,除非你需要用STDIN/STDOUT做一些有趣的事情,否则只需使用
Popen.communicate()
并且当
xclip
已经允许您将其设置为可以很好地使用Python时,您可以省去一些麻烦。