1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonでも1ファイルで済ませたい! 〜 だからシェルスクリプトと合体してみた

Last updated at Posted at 2025-11-03

最近Pythonを覚えた。
Linuxなら大抵最初から入っているので、シェルスクリプト代わりにちょい遣いできるようになりたい。
でも、やってみるとPythonめどい。
なんといっても仮想環境あってこそ、モジュールばかすか入れてこそなので、「ファイル1枚でそのまま動く」Bashスクリプトのお手軽さがまったくない。
Python動かすためにまず環境準備する必要があるとか、「最初から入っているからかんたん♪」とか秒で消滅。
めっちゃヘビーウェイトやん。

なら、シェルスクリプトと合体させて、1ファイルの中で環境も作っちゃえばいいんじゃね?
と思ってやってみた。

ここでは シェルスクリプト→Pythonの順で実装していますが、これを逆順にした転置バージョンも作ってみました。お好みでどうぞ。

#!/bin/sh
X=r''''
#
# Shell Script from here
#
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SCRIPT_PATH="$SCRIPT_DIR/$(basename "$0")"
VENV_PATH="$SCRIPT_DIR/.$(basename "$0").venv"

# Python仮想環境を作成・実行
if [ -f "$VENV_PATH/bin/activate" ]; then
  VENV_STATUS=exist
else
  python3 -m venv "$VENV_PATH"
  VENV_STATUS=new
fi
. "$VENV_PATH/bin/activate"

# 仮想環境を新規に作成した場合はpipを最新化
if [ $VENV_STATUS = new ]; then
  pip install -q --upgrade pip
fi

# 必要なパッケージをインストール
sed -n 's/^# REQUIREMENTS.TXT:\(.*\)/\1/p' "$SCRIPT_PATH" >"$VENV_PATH/requirements.txt"
pip install -qr "$VENV_PATH/requirements.txt"

# Pythonスクリプトを実行
python3 "$SCRIPT_PATH" "$@"
exit $?
: "$X" <<'##END_OF_PYTHON##' ' '''
#
# Python Script from here
#
print("Hello Python!")

##END_OF_PYTHON##
# ----------------------------------------------------------------------------
# requirements.txt from here
# REQUIREMENTS.TXT:Jinja2==3.1.6
# REQUIREMENTS.TXT:MarkupSafe==3.0.3

あとは # Python Script from here 以下にゴリゴリ書く。

解説すると、X=r''''はシェルスクリプト的には変数定義。rと空文字列2つをつなげた r という値をシェル変数Xに代入してる。
Python的にも変数定義。X=r'''...''' で複数行(シェルスクリプト部分全体)を生文字列として変数Xに代入してる。つまり、シェルスクリプト部分はPython的にはXに代入されるだけの文字列で、構文的には意味がない。
シェルスクリプト部分は、exit $? まで続く。ここで実行終了するので、それ以降は何が書いてあっても関知しない。
けど PyCharm 上でエラーが出てうざいので、 : コマンドの引数としてヒアドキュメントを渡すようにして、そのヒアドキュメントにPython部分を閉じ込める。
ついでに最初に定義したXを使っていないと警告が出るのでここで使ってあげる。
: の最後の引数が ' ''' となっているが、これは一つの空白文字と空文字列をつなげたもので、Python コメントの終端 ''' を捻り出すために置いている。
''' でPython的に文字列が終わったあとはPythonの領域。
最後に requirements.txt もgrepで抜き出せる形でコメントとして置いておく。
こんな感じ。

残念なのは、PyCharmで書いてると X=r の前に import が追加されちゃったり、うっかり全フォーマットすると X=r''''X = r'''' に整形されて、実行すると

/usr/lib/xorg/Xorg.wrap: Only console users are allowed to run the X server

なんてエラーが出たりするところ。
X = r だとシェルスクリプト的にシェル変数定義じゃなくコマンド X の実行になってしまう。残念。
あと、シェル部分で exit($?) の後ろで : コマンドを使っている部分で「到達しないコード」警告が出るのは消せなかった。残念。

いじょ。
なにぶん当方Pythonニワカなもので、同じことを実現できるもっといい「フツーのやり方」があればご教示願いたい。

2025/11/15 内容を更新しました。

  • #!/usr/bin/sh がMacでエラーになったので #!/bin/sh に変更
  • pipが古いんだが!? とMacで文句垂れられたので pip install --upgrade pip を追加
  • shファイルとして見た時に PyCharm 上で $X が未使用との警告がでたので使用した
  • sh部分の exit $? の後のエラーが気になったのでヒアドキュメントにした
  • 上記に伴う説明内容の変更
  • 転置バージョンの紹介を追記
  • シェル部分は極力短くしたいのにだんだん長くなる。。。prz
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?