Python3をインストールしてから実行するshかつpy

python3が入っていない環境でも、python3を入れてから実行できるpythonファイルを作っていた。

# 目論見

* python書いてみたい
* どうせ書くならpython3で書きたい
* どうせ書くなら他人にもつかってもらいたい
* 社内環境の標準pythonは2.4(結構辛い！)(誰も使ってない！)
* 社内の人に「python3に上げて使ってネ！」と言っても100%無理
* python3に上げる用のsh書いてもファイルが２つになって余計に心理的ハードルが上がる(と思う)
* **じゃあ実行するときに自動アップデートかけてバージョンを意識させなければいいじゃない**(ファイルも1つになるじゃない)

開発環境を誰でもrootでなんでもできるってあまりなさそうなことが前提ですが。

# 参考

[Perl, Python 及び Ruby スクリプトにおける正しいshebangの書き方]
shebang複数書けばいけるんじゃね！？と思い探しました。
まさにドンピシャで、この記事がなければこんな馬鹿なことはしませんでした。

[PHPとしても実行できるRubyの書きかた]
趣旨は違いますが、１つのファイルで複数の言語、ということでインスピレーションを受けました。こっちもやってみたい。

# コード

```sh:install_python3.py
#!/bin/sh
# -*- coding: UTF-8 -*-

""":"

# ここにshを書く

# インストールバージョンと圧縮ファイルの設置＆展開
tmp='/tmp/'
pythonver='3.4.3'
binarypath=$tmp'Python-'$pythonver

# インストール先
lib='/usr/lib/'
srcpath=$lib'python'$pythonver

# python3のシンボリックリンク設置場所
bin='/usr/bin/'
lnname='python3'

if [ -f $bin$lnname ]; then
    # python3があればそのままpython実行
    echo 'インストール不要'
    exec $lnname "$0" ${1+"$@"}
fi

echo 'インストール必要'

if [ -f $binarypath'.tgz' ]; then
    echo $binarypath'.tgz は既にあります'
else
    echo $binarypath'.tgz をダウンロードします'
    wget https://www.python.org/ftp/python/${pythonver}/Python-${pythonver}.tgz -P ${tmp}
fi

if [ -d $binarypath ]; then
    echo $binarypath' は既にあります'
else
    echo $binarypath' に展開します'
    tar zxf $binarypath'.tgz' -C $tmp
fi

if [ -d $srcpath ]; then
    echo $srcpath' へインストール済みです'
else
    echo $srcpath' へインストールします'
    # cd すると後のpython実行でコケるので、インストール後に戻る
    pwd=`pwd`
    cd $binarypath && ./configure --prefix=${srcpath} && make && make install
    cd $pwd
fi

if [ -f $bin$lnname ]; then
    echo $bin$lnname'  設置済みです'
else
    echo $bin$lnname' を設置します'
    ln -s $srcpath'/bin/python3' $bin$lnname
fi

exec $lnname "$0" ${1+"$@"}
"""

# ここからpython

import sys

version = sys.version_info
if version[0] == 2:
    print('2')
else:
    print(version[0])



```
***

最初は`python`のバージョンが2なら`python`を3に置き換えていたのですが、他に影響が出そうで、事実yumが動かなくなったりしたのでやめました。
下の失敗例はその名残ですね。

# 失敗例

**動的言語ってインタプリタで一行ずつ解析して実行すんだろ？**
**じゃあ問題がある箇所を通過しなければOKだな？**

普通に使っているときはそんなこと無いと常々痛感するのですが、一度目的が出来ると自分の都合がいい方に思い込みます。

**python内でバージョン判定し、python内でpythonを更新しようとしました**


```py

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys
import os
import tarfile

version = sys.version_info
if version[0] == 2:
    print 'バージョン2のため、3に更新します'
    if not os.path.isfile('/tmp/Python-3.4.3.tgz'):
        print 'ダウンロードします'
        os.system('wget https://www.python.org/ftp/python/3.4.3/Python-3.4.3.tgz -P /tmp')
    else:
        print '/tmp/Python-3.4.3.tgz はすでに存在しています'

    # 2.4なのでextractallはナイよー
    if not os.path.isdir('/tmp/Python-3.4.3'):
        print '/tmp/Python-3.4.3 に展開し、インストールします'
        tf = tarfile.open('/tmp/Python-3.4.3.tgz', 'r')
        tf.list()
        for item in tf:
            tf.extract(item, '/tmp/')
        # ビルド
        if not os.path.isdir('/usr/lib/python3.4.3'):
            os.system('cd /tmp/Python-3.4.3/ && ./configure --prefix=/usr/lib/python3.4.3 && make && make install')
        else:
            print '/usr/lib/python3.4.3 にインストール済みです'
    else:
        print '/tmp/Python-3.4.3 に展開済みです'


    # /usr/bin/python の置き換え
    if not os.path.isfile('/usr/bin/python.old'):
        os.rename('/usr/bin/python', '/usr/bin/python.old')
        os.symlink('/usr/lib/python3.4.3/bin/python3.4', '/usr/bin/python')
        # 既存の/usr/bin/python2 がpython へのシンボリックリンクなので更新しておく
        # 上書きはムリなので一回削除する
        os.remove('/usr/bin/python2')
        os.symlink('/usr/bin/python2.4', '/usr/bin/python2')
    else:
        print '/usr/lib/python は置き換え済みです'

    sys.exit()

# ここは3の場合に実行されるはず
print('test')

```


python2の時点で`print('test')`がセーフだったので「いける！」と思ったのですが、3に上げた時点でやっぱり`print`で`syntaxerror`
調べると、python2では`print`、`print()`どちらも使えるようで…
思い込みに拍車をかけられました(責任転嫁)

まぁ、書き始める前にちょうど[PHPの実行時とコンパイル時]を読んでまさに無理だと悟っていたのですが。

>php hoge.phpのようにコマンドにソースコードのファイルを指定して直接実行してるように見えたとしても、現代的なインタプリタはソースコードをパースしたあと仮想機械のバイトコードにコンパイルする。RubyもPythonもPerl5もEmacsも同様に。

**でも、python2側で`print`使わず、`syntax`を守ったpython3ならこれでも動くかも!?**と今思いました。


***

使用予定は無いです。

[Perl, Python 及び Ruby スクリプトにおける正しいshebangの書き方]:http://qiita.com/tueda/items/369215b99316b2e9f3d8
[PHPとしても実行できるRubyの書きかた]:http://qiita.com/supermomonga/items/79d599b4ed8b385870b0
[PHPの実行時とコンパイル時]:http://qiita.com/tadsan/items/f037095e7f07b54d3fea