如果在bash中使用管道传输,则使用子进程和xclip的Python脚本会挂起 [英] Python script using subprocess and xclip hangs if piped in bash

查看:102
本文介绍了如果在bash中使用管道传输,则使用子进程和xclip的Python脚本会挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个python脚本,需要将一些值输出到stdin并将另一个字符串复制到剪贴板.我正在使用模块subprocess通过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_ME以bash回显,并且PASTE_ME可粘贴,并立即返回.

将脚本输出传递到另一个命令时出现问题.假设有人想使用tee重定向到文件和stdin:

$ python clip.py|tee file.txt

程序按预期方式工作,但不会返回,也就是说,shell不会将控制权交还给我们.

如何解决?

一些重要信息:xclip实用程序 fork 本身(以应对X上剪贴板的实现)在外壳程序中使用时保持可复制的字符串立即返回(派生到后台).看来外壳程序将clip.pyxclip stdin/stdout都附加到了tee.
如果使用ps u找到xclip -selection clipboard并杀死了该命令,则返回.

我正在使用Python 3.4.
谢谢

解决方案

不是由于xclip的派生,而是由于Python处理Popen.wait()的方式(通过调用communicate()调用)-从Python透视图xclip(默认为静音)没有关闭其流,因此它会等待...这就是为什么一切正常的原因,除了Python在将其流传输到其他内容(在本例中为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)或所需的任何其他流句柄时将其重定向. /p>

I have a python script that needs to output some values to stdin and copies another string to clipboard. I'm using the module subprocess to execute the xclip utility through Popen something like this:

# 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()))

The script works as intended: PRINT_ME is echoed in bash and PASTE_ME is available to paste, and returns imediatly.

A problem appears when the script output is piped to another command. Suppose one wants to redirect to a file and stdin using tee:

$ python clip.py|tee file.txt

The program works as supposed but not returns, i.e. shell don't give control back.

How can this could be fixed?

Some important info: the xclip utility forks itself (to cope with implementation of clipboards on X) maintaining the string avaliable to copy, when used in shell it returns immediately (it forks to background). It appears that the shell is attaching both clip.py and xclip stdin/stdout to tee.
If xclip -selection clipboard is found using ps u and killed the command returns.

I'm using Python 3.4.
Thanks

解决方案

It's not due to forking of xclip, it's due to how Python handles Popen.wait() (which is invoked with your call to communicate()) - from Python perspective xclip (silent by default) didn't close its stream so it waits... That's why everything works except for Python moving past your p1.communicate() line when piping its streams to something else (tee in this case) - it waits for all of its file handles to close...

You can either manually open and close your streams, or just configure xclip to filter STDIN to STDOUT and keep Python happy:

import subprocess

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

Didn't test it, but it should work. If you don't want for xclip to print out to your current STDOUT just redirect it when instantiating subprocess.Popen() to None (or subprocess.DEVNULL for Python 3.x) or to any other stream handle you want.

这篇关于如果在bash中使用管道传输,则使用子进程和xclip的Python脚本会挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆