0
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Posted at

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

目論見

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

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

参考

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

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

コード

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を更新しようとしました


#!/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に上げた時点でやっぱりprintsyntaxerror
調べると、python2ではprintprint()どちらも使えるようで…
思い込みに拍車をかけられました(責任転嫁)

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

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

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


使用予定は無いです。

0
4
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
0
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?