web-dev-qa-db-ja.com

BashスクリプトでPythonを使用する

Bashスクリプトでpython=を開始しようとすると、スクリプトが実行を停止し、「Python」が呼び出された後にコマンドが実行されません。この簡単な例では、「TESTPRINT」は印刷されません。スクリプトが停止したようです。

#!/bin/bash

python

print("TESTPRINT")

Echo

Pythonに移行した後もスクリプトを実行し続けるにはどうすればよいですか?最初にAndroid Phoneにシェル化する必要があったスクリプトを書いた後、数年前に同じ問題があったと思います。そのときどのように修正したか思い出せません。

19
user364877

一連のPythonコマンドをbashスクリプトから実行するには、Pythonインタープリターに実行するコマンドをファイルから与える必要があります。 (Pythonスクリプト)次のようにスクリプトで作成します

#!/bin/bash -e

# Create script as "script.py"
cat >script.py <<'END_SCRIPT'
print("TESTPRINT")
END_SCRIPT

# Run script.py
python script.py

rm script.py

(これにより、script.pyという新しいファイルが作成されるか、既に存在する場合はそのファイルが上書きされ、Pythonに実行するように指示されます。その後、削除されます)

...または、ヒアドキュメントなど、何らかのリダイレクトを介して直接:

#!/bin/bash

python - <<'END_SCRIPT'
print("TESTPRINT")
END_SCRIPT

これはpython -を実行して、Pythonインタープリターに標準入力からスクリプトを読み取るように指示します。次に、シェルはPythonスクリプトのテキストを送信します(シェルスクリプトのEND_SCRIPT)をPythonプロセスの標準入力ストリームに追加します。

上記のコードの2つのビットは微妙に異なり、2番目のスクリプトのPythonプロセスは、読み込んでいるスクリプトに接続されている標準入力を持っていますが、最初のスクリプトはPythonプロセスは、スクリプト以外のデータを標準入力から自由に読み取ることができます。これは、Pythonコードが標準入力から読み取る場合に重要です。

Pythonは、コマンドラインから-cオプションを使用して、一連のコマンドを直接取得することもできます。

#!/bin/bash

python -c 'print("TESTPRINT")'

できないは、bashスクリプトの途中で「Pythonに切り替える」ことです。

スクリプト内のコマンドはbashによって次々に実行され、コマンドの実行中、スクリプト自体はそれが終了するのを待ちます(バックグラウンドジョブでない場合)。

つまり、元のスクリプトはPythonインタラクティブモードで開始し、bashスクリプトの実行をPythonプロセスが終了するまで一時的に中断します。その後、スクリプトはprint("TESTPRINT")をシェルコマンドとして実行しようとします。

これは、スクリプトで次のようにsshを使用する場合の同様の問題です。

ssh user@server
cd /tmp
ls

(おそらく、数年前に試したことと同じかもしれません)。

これはnotリモートシステムに接続し、そこでcdおよびlsコマンドを実行します。リモートシステムで対話型シェルを開始し、そのシェルが終了すると(スクリプトに制御を戻します)、cdおよびlsがローカルで実行されます。

代わりに、リモートマシンでコマンドを実行するには、次のコマンドを使用します。

ssh user@server "cd /tmp; ls"

(これは不十分な例ですが、要点を理解することができます)。


以下の例は、提案したことを実際に行う方法を示しています。ただし、いくつかの警告ラベルと警告が付いていますそして、このようなコードは絶対に作成しないでください(難読化されているため、メンテナンスが困難であり、あえて言うと、それはまったく悪いことです)。

python -
print("TESTPRINT")

それを実行する:

$ sh -s <script.sh
TESTPRINT

ここで何が起きるかは、スクリプトがsh -sによって実行されていることです。 sh(およびbash)の-sオプションは、標準入力ストリーム経由で到着するシェルスクリプトを実行するようにシェルに指示します。

次に、スクリプトはpython -を開始します。これは、Pythonに、標準入力ストリームから受け取ったものを実行するように指示します。 Python(したがって、スクリプトテキストファイルに接続されている)によってsh -sから継承されているため、そのストリームの次は、Python command print("TESTPRINT")

Pythonインタープリターは、スクリプトファイルからコマンドを読み取り、実行するまで、Pythonコマンドexit()が実行されるまで実行し続けます。

43
Kusalananda

Kusalanandaの回答に加えて、スクリプト全体をpythonで実行する場合は、最初の行を#!/usr/bin/env python3に変更して、通常のシェルスクリプトと同じように実行できます。どのインタープリターでどのスクリプトを実行する必要があるかを覚えておく必要はありません。

18
Akko

<<<(ここでは文字列)演算子を使用して、行に保存します。

$ python <<< 'print("MyTest")'
MyTest
9
IDDQD

pythonパスをbashスクリプトからpythonファイルを呼び出す間に設定することもできます。

export PYTHONPATH=/tmp/python_dep.Zip && python test_my.py
1
Kaushik Galiya