2017-06-14 64 views
1

我有一個python腳本,需要將一些值輸出到stdin並將另一個字符串複製到剪貼板。我使用的模塊subprocess通過Popen這樣的事情來執行xclip實用程序:使用子進程和xclip的Python腳本在bash中進行管道連接時掛起

# 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可用粘貼,和imediatly返回。

將腳本輸出傳送到另一個命令時出現問題。假設一個人想重定向到文件和標準輸入使用tee

$ python clip.py|tee file.txt 

該項目工程的設想,但沒有回報,即外殼不給控制了。

這怎麼能解決?

一些重要信息:在xclip實用本身(應付執行X上的剪貼板)保持串avaliable複製,在殼使用時,它會立即返回(它叉背景)。看起來,shell將clip.pyxclip stdin/stdout連接到tee
如果使用ps u找到xclip -selection clipboard並殺死命令返回。

我正在使用Python 3.4。
感謝

回答

0

這不是由於xclip分叉,這是由於Python中如何處理Popen.wait()(被調用與您的來電communicate()) - 從Python的角度來看xclip(默認沉默)沒有關閉其流,因此等待...這就是爲什麼一切正常,除非Python移動過你的p1.communicate()行時,它的流管道到其他的東西(tee在這種情況下) - 它等待它的所有文件句柄關閉...

你可以手動打開和關閉您的流,或者只需配置xclip即可將STDIN過濾爲STDOUT並保持Python happ y:

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)或其他您需要的流處理時重定向它。

+0

感謝您的回答,兩種方式都很好!我測試了各種修改,發現有趣的是執行'p1.communicate'之後的任何代碼(在原始缺陷代碼中),程序將暫停退出。從提出的兩個更「pythonic」和副作用的解決方案是免費的嗎? – mglart

+0

你是對的,我已經表達得很糟糕 - Popen爲xclip的STDOUT打開了一個FH(並且將它綁定到當前的STDOUT),並且由於'xclip'永遠不會關閉最後等待的流,所以它可以乾淨地退出子。至於_Pythonic_ - 這是一個虛幻的術語,對不同的人意味着不同的事物,但大多數人傾向於同意KISS方法是_Pythonic_的縮影 - 因此,除非您需要對STDIN/STDOUT進行一些操作,只需使用' POPEN。溝通()',並且在xclip已經允許你將它設置爲可以很好地與Python一起使用時節省一些麻煩。 – zwer