2013-07-02 323 views
1

子進程控制的交互我問與此相關的幾個星期前就在這裏一個問題: Python, mpg123 and subprocess not properly using stdin.write or communicate蟒蛇2.7 - 與mpg123的

多虧從那裏我能夠做什麼,我需要的時候提供幫助。 (沒有打電話給q,但是終止了子過程來停止它)##標題## 現在雖然我似乎陷入了一團糟。

from subprocess import Popen, PIPE, STDOUT 
    p = Popen(["mpg123", "-C", "test.mp3"], stdout=PIPE, stdin=PIPE, stderr=STDOUT) 
    #wait a few seconds to enter this, "q" without a newline is how the controls for the player work to quit out if it were ran like "mpg123 -C test.mp3" on the command line 
    p.communicate(input='q')[0] 

很像之前,我需要這是戒不掉了mpg123的像這將是與它的標準控件(如按「Q」退出,或「 - 」把音量調低,「+ '將音量調高等等),現在我使用上面的代碼,這在理論上應該可以工作,並且它可以用類似的程序工作。有誰知道一種方法,我可以使用內置於mpg123中的控件(可通過使用「mpg123 -C whatever.mp3」訪問的控件)使用子過程?終止是不夠的,因爲我將需要控制^ _^

編輯:非常感謝abarnert的驚人的答案=) 好吧,所以新的代碼只是一個略有修改版本的abarnert的答案,但mpg123似乎並沒有被接受的命令

import os 
    import pty 
    import sys 
    import time 

    pid, fd = os.forkpty() 
    if pid: 
     time.sleep(5) 
     os.write(fd, 'b') #this should've restarted the file 
     time.sleep(5) 
     os.write(fd, 'q') #unfortunately doesn't quit here =(
     time.sleep(5) # quits after this is finished executing 
    else: 
     os.spawnl(os.P_WAIT, '/usr/bin/mpg123', '-C', 'TEST file.mp3') 
+0

是否有理由想要控制'mpg123'播放器,而不是使用Python庫(或者甚至綁定'libmpg123')來播放音樂並執行自己的控制? – abarnert

+0

主要是因爲我是一個新手哈哈,我看到的與Raspberry Pi(我的特定平臺)播放的大部分東西都使用mpg123或mpg321,當我說我希望能夠播放mp3通過python使用一個子進程與其中一個球員 – codingNewb

+0

首先,對不起我的過度縮寫;它似乎導致你誤入歧途。每當我處理POSIX風格的代碼時,我都會回覆使用像'pid'和'fd'這樣的單詞,好像每個人都應該理解它們的意思。 'pid'是一個進程ID,而不是父ID,在這種情況下,它是_child_進程ID,因此調用它'parentID'會令人困惑。而'fd'是一個文件描述符(或者,對於真正的老年人文件描述符索引),而不是文件目錄。 – abarnert

回答

1

如果你真的需要的控件,你不能只用Popen

mpg123只啓用終端控制,如果它的標準輸入是一個tty,而不是如果它是一個文件或管道。這就是爲什麼你此行的旗幟:

Terminal control enabled, press 'h' for listing of keys and functions. 

Popen整點(和subprocess,它的建成對POSIX API)的是管道。

那麼,你能做些什麼呢?


在Linux上,你可以使用pty模塊。它也可能在其他* nix平臺上工作,但它可能不會 - 即使它被構建幷包含在stdlib中。正如文檔所說:

因爲僞終端處理是高度依賴於平臺的,所以有代碼只對Linux執行。 (Linux代碼應該可以在其他平臺上工作,但還沒有經過測試。)

它確實運行在2.7和3.3的BSD平臺上,並且文檔中的示例似乎適用於Mac OS X和FreeBSD ......但就我所查過的而言。


與此同時,大部分POSIX平臺將至少有os.forkpty,這不是更難,所以這裏的播放作爲其第一個參數傳遞的一首歌的前5秒一個簡單的程序:

import os 
import pty 
import sys 
import time 

pid, fd = os.forkpty() 
if pid: 
    time.sleep(5) 
    os.write(fd, 'q') 
else: 
    os.spawnl(os.P_WAIT, # mode 
       '/usr/local/bin/mpg123', # path 
       '/usr/local/bin/mpg123', '-C', sys.argv[1]) # args 

請注意,我上面使用了os.spawnl。這大概是而不是你想要的是一個真正的程序;這是出於教學目的,鼓勵你閱讀文檔(和相應的手冊)並理解這一系列功能。

由於the docs的解釋,這並不使用PATH環境變量,因此您需要指定程序的完整路徑。您可以使用spawnlp而不是spawnl來解決此問題。

此外,spawn可能(事實上,總是這樣做,雖然文檔不完全清楚)做另一個叉子來執行孩子。這確實沒有必要,但spawn會執行您需要手動執行的操作,如果您只需撥打exec即可。如果您知道自己在做什麼,則可能需要使用execl(或execlp)而不是spawnl

你甚至可以使用大多數的subprocess的功能,只要你小心(不產生任何管道,並記住,你最終會做2個fork S,所以一定要設立父母/子女關係)。

還要注意的是,你需要的路徑傳遞到mpg123兩次 -once作爲路徑,然後一旦爲孩子計劃的argv[0]。你也可以第二次通過mpg123。或者,理想情況下,看看當你從shell運行它時所說的ps,並通過它。無論如何,你必須通過作爲argv[0];否則,-C結束是在argv[0],這意味着mpg123的不會認爲你給了它一個-C標誌,使控制鍵,但不是你把它改名爲-C和沒有標誌跑了......

不管怎樣,你真的確實需要閱讀文檔來理解這些函數的作用,而不是僅僅把它看作你不瞭解的魔法代碼。所以,我故意用最簡單的解決方案來鼓勵。


在Windows上,有沒有這樣的事,作爲一個pty,沒辦法帶內置到Python的工具來做到這一點的。您需要使用各種第三方庫之一來控制cmd.exe控制檯(又名DOS提示符)。

+0

這看起來很有前途;謝謝^ _ ^不幸的是它是全新的因此我必須去閱讀文檔,看看我能不能找到教程^ _^ – codingNewb

+1

我無法得到示例代碼開始工作,雖然稍作修改,但...而不是'/ usr/local/bin/mpg123',它位於'/ usr/bin/mpg123'中。有時間修補,再次感謝你^ _^ – codingNewb

+0

@newbToPython:我假設你知道你安裝了'mpg123'的地方。但是這提出了一個很好的觀點:使用'subprocess'你不必擔心'PATH';使用'os.spawn *'變體,你必須閱讀文檔並思考它。讓我更新答案來解釋。 – abarnert