[英]subprocess.call does not wait for the process to complete
根據Python文檔, subprocess.call
應該阻塞並等待子進程完成。 在這段代碼中,我試圖通過在命令行上調用Libreoffice
將少量xls
文件轉換為新格式。 我假設對子進程調用的調用是阻塞的,但似乎我需要在每次調用后添加一個人工延遲,否則我會錯過out
目錄中的幾個文件。
我究竟做錯了什么? 為什么我需要延遲?
from subprocess import call
for i in range(0,len(sorted_files)):
args = ['libreoffice', '-headless', '-convert-to',
'xls', "%s/%s.xls" %(sorted_files[i]['filename'],sorted_files[i]['filename']), '-outdir', 'out']
call(args)
var = raw_input("Enter something: ") # if comment this line I dont get all the files in out directory
編輯通過以下評論可能很難找到答案。 我使用unoconv
進行文件轉換,這種轉換阻塞並且易於使用腳本。
這是
可能的
可能libreoffice
作為某種守護/中介過程的實現。 “守護進程”將(實際上1 )解析命令行,然后將工作分配給其他進程,可能會將它們分離,以便它可以立即退出。 (基於文檔中的-invisible
選項,我強烈懷疑這確實是你的情況)。
如果是這種情況,那么你的subprocess.call
會做它所宣傳的事情 - 在繼續之前等待守護進程完成。 但是,它不會做你想要的等待所有工作完成的事情。 您在該場景中唯一的選擇是查看守護程序是否具有-wait
選項或類似選項。
1我們這里可能沒有實際的守護進程 ,只有表現相似的東西。 見abernert的評論
問題是, soffice
命令行工具( libreoffice
只是一個鏈接,或者是另一個包裝器)只是真實程序soffice.bin
的“控制器”。 它找到soffice.bin
的運行副本和/或創建on,告訴它做一些工作,然后退出。
因此, call
正在做正確的事情:它等待libreoffice
退出。
但你不想等待libreoffice
退出,你想等soffice.bin
完成libreoffice
要求它做的工作。
看起來你正在嘗試做的事情是不可能直接做的。 但它可以間接地做。
文檔說無頭模式:
...允許使用沒有用戶界面的應用程序。
當應用程序由外部客戶端通過API控制時,可以使用此特殊模式。
換句話說,在運行一些UNO字符串/進行一些轉換/在命令行上指定的任何其他內容后,應用程序不會退出,它會等待來自外部的更多UNO命令,而啟動器只是在發送時立即運行應用程序的相應命令。
您可能必須直接使用上述外部控制API(UNO)。
有關基礎知識,請參閱腳本LibreOffice (盡管有關於內部腳本的信息比外部更多),以及有關詳細信息和示例的API文檔 。
但是可能有一個更簡單的答案: unoconv
是一個簡單的命令行工具,使用UNO API編寫,完全符合您的要求。 如有必要,它會啟動LibreOffice,發送一些命令,等待結果,然后退出。 因此,如果您只使用unoconv
而不是libreoffice
,則只需call
。
另請注意, unoconv
是用Python編寫的,旨在用作模塊。 如果只是import
它,您可以編寫自己的(更簡單,特定於用例)代碼來替換“主入口”代碼,而根本不使用subprocess
。 (或者,當然,您可以撕開模塊並自己使用相關代碼,或者只是將它用作從Python中使用UNO的非常好的示例代碼。)
此外,上面鏈接的unoconv
頁面列出了各種其他類似工具,一些通過UNO工作,一些不工作,所以如果它不適合你,請嘗試其他工具。
如果沒有其他工作,你可以考慮,例如,創建一個sentinel文件和使用文件系統監視,所以至少你將能夠准確地檢測它何時完成其工作,而不必猜測超時。 但這是一個真正的最后溝渠解決方案,在消除所有其他選項之前,您甚至不應該考慮這個問題。
如果libreoffice正在使用@mgilson提到的中介(守護進程),那么一個解決方案是找出它正在調用的程序,然后直接自己調用它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.