かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

Python zsh で仮想環境 venv に入れない?にハマる

Python の venv で作成した仮想環境に入れない問題にハマったのでメモ

venv

Python v3.3 から標準機能として取り入れられた仮想環境
venv 内では pip でインストールされるパッケージが仮想環境ごと別にすることができる

仮想環境の作成

$ python -m venv testvenv

testvenv というディレクトリに仮想環境が作成される

仮想環境の実行

仮想環境内の bin/activate を実行すると仮想環境に入れる

$ source testvenv/bin/activate
(testvenv) 
# 仮想環境から出る
(testvenv) deactivate

と、簡単に仮想環境が作成できて実行できる筈だった…

zsh で仮想環境が実行されない?

環境

zsh で venv 環境を作成して実行しようとしても何も起こらなかった

$ python -m venv testvenv
$ source testvenv/bin/activate
$

zsh の見たをカスタマイズしているのが問題だった

実際には仮想環境は実行されていたが、zsh をカスタマイズしていたために、仮想環境に入っていることの表示がされていないだけでした。
Powerlevel9k でカスマイズしていたので、表示に virtualenv を加えると仮想環境に入っていることが表示されるようになりました。

# .zprofile
POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(ssh dir vcs newline virtualenv status)

👇

$ python -m venv testvenv
$ source testvenv/bin/activate
(testvenv) $

自分のしていたカスタマイズが原因だったので、原因が解るまで時間がかかってしまった…
zsh のカスタマイズパッケージの Powerlevel9k も Powerlevel10k を使うように言われているのですね…

それにしても Python の仮想実行環境簡単に作れるので驚きました


[参考]

Python3のTrueとFalse、それからNone

PythonのboolはTrueFalse
truefalseと小文字にするとエラーになる。

  • 0, 0.0, [], {}, "", Noneはbool化するとFalse
  • Trueは、1扱いにもなる
  • Falseは、0, 0.0扱いにもなる

Bool化

bool(0)    # False
bool(0.0)  # False
bool([])   # False
bool({})   # False
bool("")   # False
bool(None) # False
bool(1)    # True
bool(2)    # True
bool(-1)   # True
  • Noneはbool化するとFalse
  • 数値は0以外はTrueになる

==

==演算子は「等価(同じ値)」かを比較する

True ==
True == True  # True
True == False # False
True == None  # False
True == 1     # True
True == 2     # False

数値は1以外はTrueにはならない

False ==
False == True  # False
False == False # True
False == None  # False
False == 0     # True
False == 0.0   # True
False == []    # False
False == {}    # False
False == ""    # False
False == -1    # False

[], {}, "", Noneはbool化するとFalseだが、Falseとは等しくない。(==Falseになる)

None ==
None == True  # False
None == False # False
None == None  # True
None == 0     # False
None == 0.0   # False
None == []    # False
None == {}    # False
None == ""    # False

Noneと等しくなるのはNoneのときだけ。

is

is演算子は「同一のオブジェクトか」を判定する

追記 is を判定していたプログラムに誤りがあり True is True, False is False, None is NoneFalse になると書いていましたが、正確にはこれはら True になるが正しいので記事を訂正しました。

True is
True is True # True
True is 1    # False

True is TrueTrue だが、 ==ではTrueになっていた1is演算子で比較するとFalse

False is
False is False # True
False is 0     # False
False is 0.0   # False

False is FalseFalseだが、 Falseも同様に==ではになっていた 00.0is演算子ではFalse

None is
None is None # True

NoneNone == None のときと同じで None is None のときは True

int化

int(True)  # 1
int(False) # 0
int(None)
# TypeError: int() argument must be a string, a bytes-like object or a number, not 'NoneType'

True1False0int(None)はエラーになる。

暗黙の型変換?が行われる処理だと、True1False0として扱われる

True > False # true
3 + true     # 4
"7" - False
# => TypeError: unsupported operand type(s) for -: 'str' and 'bool'

数値にTrueを足すのは+1と同じ扱いになる。
javascriptのように- 0で数値化はできない。

PythonTrueFalseRubyfalsenilの時だけfalseで後はtrueに比べて、ちょっと複雑でした。
特にbool(2)Trueだけど、2 == TrueFalseとかはちょっと紛らわしい...


==, is の比較を試してみたコード

def ifEq(v):
    arg = [True, False, None, 0, 0.0, 1, 2, -1, [], {}, ""]
    str_v = str(v)
    for val in arg:
        if v == val:
            print(f"{str_v} == {str(val)} # True")
        else:
            print(f"{str_v} == {str(val)} # False")

def ifIs(v):
    arg = [True, False, None, 0, 0.0, 1, 2, -1, [], {}, ""]
    str_v = str(v)
    for val in arg:
        if v is val:
            print(f"{str_v} is {str(val)} # True")
        else:
            print(f"{str_v} is {str(val)} # False")

print("\n>> True ==")
ifEq(True)

print("\n>> False ==")
ifEq(False)

print("\n>> None ==")
ifEq(None)

print("---------------")

print("\n>> True is")
ifIs(True)

print("\n>> False is")
ifIs(False)

print("\n>> None is")
ifIs(None)

実行してみることができます 👉 Online PHP/Java/C++... editor and compiler | paiza.IO


[参考]

HomebrewでpyenvをアップデートしたらPythonが動かなくなった

HomebrewでpyenvをインストールしてPython環境を作っていました。

brew upgradepyenvがアップデートされた後Pythonを実行しようとしたら次のようなエラーが出るようになってしまいました。

$ python
/Users/user_name/.pyenv/shims/python: line 21: /usr/local/Cellar/pyenv/1.2.4/libexec/pyenv: No such file or directory

.pyenv/shims/pythonの中をエディタで見ると、pyenvのパスがベタで書かれていたので、brew upgradepyenvのバージョンが上がり読み込めなくなっていたのが原因のようでした。

pyenvのパスを再設定 (pyenv rehash)

$ pyenv rehash

このコマンドを実行すると.pyenv/shims/pythonのパスが再設定され無事Pythonが実行できるようになりました。

$ pyenv --help
...
   rehash      Rehash pyenv shims (run this after installing executables)

.pyenv/shims/pythonの中にあるパスを直接書き換えるのは、他にも影響がある可能性があるのであまりよろしくないでしょう。

pyenvをアップデートしたら、忘れなずpyenv rehashを実行する。
自動的に実行して欲しさ若干ありますが


[参考]

Pythonスタートブック [増補改訂版]

Pythonスタートブック [増補改訂版]