我有一个 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.py
和 xclip
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/