Pythonでシェルプロンプトを取得する

Pythonでシェルプロンプトを取得する

Pythonスクリプトから(zsh)シェルプロンプトを取得したいと思います。ただ使用

import os
prompt = os.environ['PS1']

PS1通常、子プロセスへの転送は行われないため、正しいアプローチではないようです。env | grep PSシェルでも同じ方法で失敗します。

そこで、インタラクティブシェルをサブプロセスとして起動し、プロンプトを照会する必要があるという結論に達しました。シェルでできること

zsh -c -i 'echo $PS1'

(一重引用符でなければならず、二重引用符は失敗します。)

私はpython(2.7)で次のように同じことをしようとしていますsubprocess

print subprocess.check_output(['-i','-c',r"'echo $PS1'"],executable="/bin/zsh")

これは失敗しました

subprocess.CalledProcessError: Command '['-i', '-c', "'echo $PS1'"]' returned non-zero exit status 127

私はそれが原因だとは思わないが、$PS1むしろecho-partをパラメータとして提供する方法のために、裸の文字列をこのようにエコーすることも失敗するからです。

行き来しながら様々な組み合わせを試みる

prompt =  subprocess.check_output("""zsh -c -i 'echo $PS1'""",shell=True,executable="/bin/zsh")

これはアクションを実行しているようですが、これはシェルを起動してそのシェル内で別のシェルを呼び出すため、私にとっては間違っているようです-c -i 'echo $PS1'

シェルプロンプトを取得する正しい方法は何ですか?

答え1

print subprocess.check_output(['zsh','-i','-c','echo $PS1'])

別のシェルで実行している場合は、文字列全体が単一引数として渡されるように、二重zsh引用符が必要です。彼らはそうしなければならないecho $PS1-c一つ二重引用符内に最初のシェルが拡張されているため、引用符があります$PS1

Pythonでは、コマンド全体が単一の文字列なので、他の文字列のように引用されます。 2番目のグループを追加することは'echo $PS1'(引用符を含む)を入力するのと同じですzsh。シェルは名前付き実行ファイルを見つけますが、見つかりません'echo $PS1'

答え2

正しい方法は、次のようにサブプロセスを呼び出すことです。

>>> prompt = subprocess.check_output("""echo $PS1""",shell=True,executable="/bin/zsh")

その後、結果を確認するか、>>> prompt Enter 呼び出しを使用して結果を直接確認できます。

>>> subprocess.call("""echo $PS1""",shell=True,executable="/bin/zsh")

zshしたがって、コマンド自体を呼び出す必要はありません。

Popen以下を使用して対話型通信を実行できます。

>>> Popen(["/bin/zsh"], stdout=PIPE).communicate()[0]
SHELL_PROMPT% echo $PS1    
SHELL_PROMPT% exit  # exit to see the result of command   

これについて詳しくは、次をご覧ください。サブプロセス

shell=True上記のリンクの使用に関する警告も参照してください。

警告:信頼できないソースから削除されていない入力を含むシェルコマンドを実行すると、プログラムがランダムなコマンド実行につながる可能性がある重大なセキュリティ上の欠陥であるシェル注入に脆弱になります。したがって、コマンド文字列が外部入力で構成されている場合は、shell = Trueを使用することはお勧めできません。

>>> from subprocess import call
>>> filename = input("What file would you like to display?\n")
What file would you like to display?
non_existent; rm -rf / #
>>> call("cat " + filename, shell=True) # Uh-oh. This will end badly...
shell=False does not suffer from this vulnerability; the above Note may be helpful in getting code using shell=False to work.

関連情報