如果在bash中通过管道传输,则使用子流程和xclip的Python脚本将挂起
我有一个python脚本,需要将一些值输出到stdin并将另一个字符串复制到剪贴板。我使用模块如果在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
子流程
通过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时,您可以省去一些麻烦。