Pythonお悩み解決

Pythonに関する疑問や悩みにこたえるブログです

仮想環境の使い方を知りたい(venvの基本)

Pythonで実際の開発する場合、以下のようなことをしたいと考えるでしょう。

  • プロジェクト毎にパッケージを管理したい
  • プロジェクト毎にPythonのバージョンを指定したい

Pythonでは仮想環境という仕組みを使って、これを実現できます。

今回はPython仮想環境と、仮想環境を扱うvenvの基本的な使い方について解説します。

Pythonの仮想環境とは

Pythonの仮想環境とは、独立したPython環境のことです。

「独立した」とは、その仮想環境の中にインストールされたPythonインタープリタやパッケージが、他の仮想環境にインストールされたものから隔離されている、ということです。

さらに、仮想環境はシステム(OS)のPython環境にインストールされたパッケージからも隔離されています。

そのため仮想環境を使うことで、プロジェクト毎にパッケージを管理したり、Pythonのバージョンを指定できるようになります。

仮想環境を使うには、Pythonに標準でインストールされているvenvを利用します。

venvの基本的な使い方

venvは標準ライブラリに含まれるモジュール*1なので、Pythonをインストールすればすぐに使えます。

仮想環境の作成

まずは、venvを使って仮想環境を作成します。作成方法は、コマンドプロンプトWindowsの場合)やターミナル(macOSの場合)で以下のようなコマンドを実行します。

python -m venv <仮想環境のパス>

macOSなどの場合は、pythonコマンドではなくpython3コマンドです(pythonだとPython 2.7が使われる可能性があります)。

python3 -m venv <仮想環境のパス>

-m venvでvenvモジュールを、<仮想環境のパス>でvenvモジュールに渡す引数を指定しています。

<仮想環境のパス>は任意ですが、venvenvなどが使われることが多いです。ここではsample-venvとし、任意の空ディレクトリ下で実行してみます。

python3 -v venv sample-venv

すると、sample-venvというディレクトリ(フォルダ)が作成されます。なお、このディレクトリの名前は、仮想環境の作成時に指定した<仮想環境のパス>になります。

このディレクトリの内容を、少し確認してみましょう。内容は環境によって多少異なります。

sample-venv/
├── bin/
├── include/
├── lib/
└── pyvenv.cfg

このように、仮想環境の実体はPython実行ファイルなど幾つかのファイルを含んだディレクトリです。

便利なオプション

仮想環境を作成すると、仮想環境にはpipなどがインストールされた状態になっていますが、バージョンが古いことがあります。

仮想環境を有効化後、以下のコマンドでpipを最新化できますが、少々面倒です。

pip install --upgrade pip

これについて、Python 3.9からは--upgrade-depsというオプションが追加されました。

このオプションをつけて仮想環境を作成すると、pipなどが最新化された状態で仮想環境が作成されます。

python -m venv --upgrade-dep <仮想環境のパス>

仮想環境の有効化

仮想環境を作成しただけでは、まだ仮想環境を利用している状態にはなっていません。

作成した仮想環境を使うには、仮想環境を有効化する必要があります。

環境やお使いのシェルによって、実行するスクリプトが異なります。

Windowsの場合(コマンドプロンプト

sample-venv¥Scripts¥activate.bat

macOS/Linuxの場合(bash/zsh

source sample-venv/bin/activate

上記のsample-venvの部分はそれぞれの<仮想環境のパス>で置き換えてください。

以降はmacOSを使って解説します。

仮想環境が有効化されると、以下のように、プロンプトに利用中の仮想環境がつきます((sample-venv)の部分です)。

$ source sample-venv/bin/activate
(sample-venv) $ 

ためしにpythonコマンドのバージョンやパスを確認すると、仮想環境の有効化後は仮想環境内のpythonが使われるようになっています。

# 仮想環境が有効な状態
(sample-venv) $ python -V
Python 3.10.6
(sample-venv) $ which python
/Users/testuser/venv-sample/venv/bin/python
# 仮想環境が無効な状態
$ python -V
Python 2.7.13
$ which python
/usr/local/bin/python
注意点

仮想環境を有効化しても、それはそのコマンドプロントやターミナルに限られます。システム全体のPython環境が仮想環境になるわけではありません。

そのため、新たにコマンドプロントやターミナルを立ち上げた場合、その中では仮想環境は有効になっていません。

複数のコマンドプロントやターミナルで仮想環境を使いたい場合は、それぞれの中で有効化する必要があります。

仮想環境の無効化

仮想環境の利用を停止する場合は、仮想環境を無効化します。

無効化するためのコマンドはdeactivateです。

このコマンドは仮想環境を有効化した時に、利用できるようになっています。

(sample-venv) $ deactivate
$ 

プロンプトに付いていた(sample-venv)が無くなりました。これで仮想環境が無効化されたことになります。

仮想環境の削除

仮想環境を削除するには、仮想環境のディレクトリを削除するだけで大丈夫です。

特別なコマンドなどはありません。

仮想環境ごとにPythonのバージョンを分ける方法

仮想環境におけるPythonのバージョンは、仮想環境の作成に使用したPythonのバージョンになります。

そのため、たとえばPython 3.9で仮想環境を作成したら、仮想環境のPythonのバージョンも3.9になります。

試しにPython 3.9で仮想環境を作成し、有効化してみます。macOSではpython3.9のようにバージョンを付けたコマンドが実行できます。*2

$ python3.9 -m venv venv39

Windowsの場合は、インストールしたPythonのフルパスを指定します。*3

>C:\Users\testuser\AppData\Local\Programs\Python\Python39\python -m venv venv

仮想環境を有効化し、pythonのバージョンを確認してみます。

$ source venv39/bin/activate
(venv39) $ python -V
Python 3.9.12

先ほどの仮想環境(sample-venv)はPython 3.10でしたが、今回の仮想環境(venv39)はPython 3.9になっていることが確認できました。

このように、仮想環境ごとにPythonのバージョンを指定できます。

なお、パッケージ管理の方法については、また別の記事で解説したいと思います。

まとめ

  • Pythonの仮想環境は、独立したPython環境
  • 仮想環境を使うと、プロジェクトごとにパッケージ管理したり、Pythonのバージョンを指定できる
  • 仮想環境の作成にはvenvを使う
  • 仮想環境を使うには、仮想環境を有効化する必要がある

参考

*1:Python 3.3から標準ライブラリに追加されました

*2:もちろん対応するPythonがインストールされている必要があります

*3:Microsoft Storeからインストールした場合は、python3.9などバージョン付きのコマンドが使えます

【エラー解説】NameErrorとは?原因と対応方法

今回はPythonNameErrorについて解説します。

1. NameErrorとは

NameErrorPythonの組み込み例外の1つで、「名前が見つからなかった」というエラーです。

このエラーは、変数や関数などを参照した際、その名前が見つからなかった場合に発生します。

いくつか発生ケースを見てみましょう。

以下は、Python 3.10で実行しています。

変数名が見つからない

>>> colors = ["red", "green", "blue"]
>>> color
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'color' is not defined. Did you mean: 'colors'?

関数名が見つからない

>>> def add_one(num):
...     return num + 1
...
>>> add_ona(10)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'add_ona' is not defined. Did you mean: 'add_one'?

クラス名が見つからない

>>> class Animal:
...     def __init__(self, name):
...         self.name = name
...
>>> my_pet = Animel("ポチ")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'Animel' is not defined. Did you mean: 'Animal'?

他にも発生ケースは考えられますが、いずれも「指定した名前が見つからない」ことが原因で発生します。

エラーメッセージの末尾に、Did you mean: 'colors'?のように間違えている名前の候補が表示されます。

これをヒントに、名前の指定が正しいかを確認するとよいでしょう。

ちなみに、エラーメッセージの末尾にあるDid you mean:以降の部分は、Python 3.10以降で表示されるようなりました。

Python 3.9以前では、以下のようにDid you mean:は表示されません。

>>> # Python 3.9 で実行した場合
>>> colors = ["red", "green", "blue"]
>>> color
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'color' is not defined

なお、NameErrorが発生するのは、ローカルまたはグローバルの名前が見つからなかった場合です。

辞書のキー名や、オブジェクトの属性名が見つからなかったには、別エラーが発生します(関連記事を参照)。

2. NameErrorの対応方法

NameErrorの原因は、タイプミスなど、単純なミスであることが多いです。

NameErrorが発生したら、指定した変数名や関数名が正しいかを確認しましょう。

3. まとめ

  • NameErrorは、参照した名前(変数名など)が見つからなかった場合に起きるエラー
  • NameErrorが発生したら、指定した名前が正しいかを確認する

関連記事

python-onayami.com

日時を表す文字列を日時データに変換したい

Pythonで「日時を表す文字列を日時データに変換する方法」を解説します。

Pythonで文字列を日時データを文字列に変換するには、主に2つの方法があります。

それぞれ見ていきましょう。

1. fromisoformat()メソッドを使う

まずは、ISO 8601書式で表された日時の文字列を日時データに変換する方法です。

ISO 8601書式では、たとえば年-月-日T時:分:秒のように日時を表します(他にもバリエーションがあります)。

このISO 8601書式の文字列を日時データに変換するには、fromisoformat()メソッドが使えます

fromisoformat()datetimeクラスのクラスメソッドで、Python 3.7で追加されました。

このメソッドの使い方は以下の通りです。

datetime.fromisoformat(ISO書式の文字列)

なおfromisoformat()datetimeクラスだけなく、dateクラスとtimeクラスでも使えます。

各クラスの使用例を見ていきましょう。

datetime.fromisoformat()の例

datetimeクラスの場合、たとえば以下のような文字列をdatetimeオブジェクトに変換できます。

>>> from datetime import datetime
>>> # "2022-07-06T12:34:56" を datetime型 に変換
>>> datetime.fromisoformat("2022-07-06T12:34:56")
datetime.datetime(2022, 7, 6, 12, 34, 56)
>>> # "2022-07-06 12:34:56.789" を datetime型 に変換
>>> datetime.fromisoformat("2022-07-06 12:34:56.789")
datetime.datetime(2022, 7, 6, 12, 34, 56, 789000)
>>> # "2022-07-06" を datetime型 に変換
>>> datetime.fromisoformat("2022-07-06")
datetime.datetime(2022, 7, 6, 0, 0)

date.fromisoformat()の例

dateクラスの場合は、年-月-日という書式の文字列をdateオブジェクトに変換できます。

>>> from datetime import date
>>> # "2022-07-06" を date型 に変換
>>> date.fromisoformat("2022-07-06")
datetime.date(2022, 7, 6)

time.fromisoformat()の例

timeクラスの場合は、時:分:秒時:分:秒.マイクロ秒のような時刻の文字列をtimeオブジェクトに変換できます。

>>> from datetime import time
>>> # "12:34:56" を time型 に変換
>>> time.fromisoformat("12:34:56")
datetime.time(12, 34, 56)
>>> # "12:34:56.789" を time型 に変換
>>> time.fromisoformat("12:34:56.789")
datetime.time(12, 34, 56, 789000)
>>> # "12:34:56.778899" を time型 に変換
>>> time.fromisoformat("12:34:56.778899")
datetime.time(12, 34, 56, 778899)

文字列の書式が合わない場合

文字列がISO 8601書式に合わない場合は、ValueErrorが発生します。

>>> datetime.fromisoformat("2022/07/06")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: Invalid isoformat string: '2022/07/06'

このように「不正なISO書式の文字列(Invalid isoformat string)」というエラーメッセージが表示されます。

isoformat()との関係

fromisoformat()メソッドはisoformat()メソッドの逆関数(入力と出力が逆になる関数)となっています。

そのため、fromisoformat()メソッドで変換できるのは、isoformat()メソッドで出力される書式の文字列だけです。

ISO 8601書式は上記以外にもいくつか書き方がありますが、それら全ての書き方に対応しているわけではないことに注意しましょう。

isoformat()については、別の記事で解説していますので、末尾の「関連記事」をご参照ください。

2. strptime()メソッドを使う

任意の書式の文字列を日時データに変換したい場合は、datetimeクラスのstrptime()メソッドを使います

このメソッドの使い方は以下の通りです。

datetime.strptime(日時の文字列, 書式)

書式は、以下のように書式化指定子を使って任意の書式を指定できます。

>>> from datetime import datetime
>>> # "年/月/日 時:分:秒" という書式の文字列を変換
>>> datetime.strptime("2022/07/06 12:34:56", "%Y/%m/%d %H:%M:%S")
datetime.datetime(2022, 7, 6, 12, 34, 56)

%Y%mの部分が書式化指定子です。

時刻を含まない場合、以下のようにdatetimeオブジェクトの時刻部分は0になります。

>>> # "年/月/日" という書式の文字列を変換
>>> datetime.strptime("2022/07/06", "%Y/%m/%d")
datetime.datetime(2022, 7, 6, 0, 0)

よく使う書式指定子は以下のようなものがあります。

書式指定子 意味 使用例
%Y 西暦(4桁) 0001, 0002, ..., 2022, 2023, ..., 9998, 9999
%y 西暦(2桁) 00, 01, ..., 99
%m 01, 02, ..., 12
%B 月名 January, February, ..., December
%b 月名(短縮系) Jan, Feb, ..., Dec
%d 日にち 01, 02, ..., 31
%A 曜日名 Sunday, Monday, ..., Saturday
%a 曜日名(短縮系) Sun, Mon, ..., Sat
%H 時(24時間表記) 00, 01, ..., 23
%I 時(12時間表記) 01, 02, ..., 12
%p AM/PM AM, PM
%M 00, 01, ..., 59
%S 00, 01, ..., 59
%f マイクロ秒 000000, 000001, ..., 999999

なお、strptime()datetimeクラスのみに存在し、dateクラスやtimeクラスには存在しません。

文字列の書式が合わない場合

文字列が指定した書式と合わないとVallueErrorが発生します。

>>> datetime.strptime("2022-07-06", "%Y/%m/%d")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/_strptime.py", line 568, in _strptime_datetime
    tt, fraction, gmtoff_fraction = _strptime(data_string, format)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/_strptime.py", line 349, in _strptime
    raise ValueError("time data %r does not match format %r" %
ValueError: time data '2022-07-06' does not match format '%Y/%m/%d'

このように「書式が合ってない(does not match format)」というエラーメッセージが表示されます。

メソッド名の覚え方:strptime()pとは

strptime()と似た名前のメソッドに、strftime()があります。

私はこの2つをなかなか区別できなったのですが、pfの意味が分かったら簡単に覚えられました。

strptime()pparsepです。

「パース(parse)」は「解析する」という意味なので、strptime()は文字列を解析(parse)して、日時データに変換するメソッドと覚えましょう。

strftime()については、別の記事で解説していますので、末尾の「関連記事」をご参照ください。

3. まとめ

  • ISO 8601書式の文字列を日時データに変換には、fromisoformat()メソッドが使える
    • 対応クラス:datetime date time
  • 任意の書式の文字列を日時データに変換する場合は、datetimeクラスのstrptime()メソッドを使う

関連記事

isoformat()strftime()については、こちらの記事で解説しています。

python-onayami.com

参考情報

日時データを文字列に変換したい

Pythonで日時データを文字列に変換する方法を解説します。

Pythonで日時データを文字列に変換するには、主に2つの方法があります。

それぞれ見ていきましょう。

1. isoformat()メソッドを使う

1つめはisoformat()メソッドを使う方法です。

これは年-月-日T時:分:秒.マイクロ秒のような書式で日時を表現します。

例として、datetimenow()メソッドで取得した現在日時(datetime型のオブジェクト)を、isoformat()メソッドで変換してみましょう。

>>> from datetime import datetime
>>> # 現在日時を取得
>>> dt = datetime.now()
>>> dt
datetime.datetime(2022, 7, 4, 20, 24, 54, 746371)
>>> # isoformat()で文字列に変換
>>> dt.isoformat()
'2022-07-04T20:24:54.746371'

日時データ(dt)が、年-月-日T時:分:秒.マイクロ秒という書式の文字列になったことを確認できました。

なお、マイクロ秒が0であれば、年-月-日T時:分:秒になります。

>>> # マイクロ秒が「0」の日時データを作成
>>> dt = datetime(2022, 7, 4, 12, 34, 56)
>>> dt
datetime.datetime(2022, 7, 4, 12, 34, 56)
>>> # isoformat()で文字列に変換
>>> dt.isoformat()
'2022-07-04T12:34:56'

また、isoformat()メソッドはdatetime型のオブジェクトだけでなく、date型やtime型のオブジェクトでも使えます。

date型のオブジェクトでisoformat()を使用した場合、以下のように年-月-日となります。

>>> from datetime import date
>>> td = date.today()
>>> td
datetime.date(2022, 7, 4)
>>> td.isoformat()
'2022-07-04'

time型のオブジェクトでisoformat()を使用した場合、以下のように時-分-秒となります(マイクロ秒が含まれる場合は時:分:秒.マイクロ秒)。

>>> from datetime import time
>>> t = time(12, 34, 56)
>>> t.isoformat()
'12:34:56'

なお、この書式は日付と時刻の表記に関する国際規格であるISO 8601に従っています。

日時をISO書式で表したい場合は、isoformat()メソッドを使うとよいでしょう。

2. strftime()メソッドを使う

2つめはstrftime()メソッドを使う方法です。

こちらは書式指定子を使い、自分で日時の書式を指定できます

たとえば、年/月/日 時:分:秒という書式の文字列に変換したい場合、以下のようにします。

>>> dt = datetime(2022, 7, 4, 12, 34, 56)
>>> # 「年/月/日 時:分:秒」という書式にする
>>> dt.strftime("%Y/%m/%d %H:%M:%S")
'2022/07/04 12:34:56'

%Y%mなどが書式指定子です。

よく使う書式指定子は以下のようなものがあります。

書式指定子 意味 使用例
%Y 西暦(4桁) 0001, 0002, ..., 2022, 2023, ..., 9998, 9999
%y 西暦(2桁) 00, 01, ..., 99
%m 01, 02, ..., 12
%B 月名 January, February, ..., December
%b 月名(短縮系) Jan, Feb, ..., Dec
%d 日にち 01, 02, ..., 31
%A 曜日名 Sunday, Monday, ..., Saturday
%a 曜日名(短縮系) Sun, Mon, ..., Sat
%H 時(24時間表記) 00, 01, ..., 23
%I 時(12時間表記) 01, 02, ..., 12
%p AM/PM AM, PM
%M 00, 01, ..., 59
%S 00, 01, ..., 59
%f マイクロ秒 000000, 000001, ..., 999999

なお、strftime()メソッドはdate型やtime型のオブジェクトでも使えます。

日時を表す書式を自分で指定したい場合は、strftime()メソッドを使うとよいでしょう。

メソッド名の覚え方:strftime()fとは

strftime()と似た名前のメソッドに、strptime()があります。

私はこの2つをなかなか区別できなったのですが、fpの意味が分かったら簡単に覚えられました。

strftime()fformatfです。

「フォーマット(format)」は「書式」ということなので、strftime()は日時データを指定した書式(format)で表すメソッドと覚えましょう。

strptime()については別の記事で解説予定です。

3. まとめ

  1. 日時データを文字列に変換するには、isoformat()strftime()を使う
    • 日時データ:datetime型、date型、time型のオブジェクト
  2. 日時をISO書式で表したい場合は、isoformat()メソッドを使う
    • ISO書式:年-月-日T時:分:秒.マイクロ秒など
  3. 日時を表す書式を自分で指定したい場合は、strftime()メソッドを使う

参考情報

【エラー解説】KeyErrorとは?原因と対応方法

今回はPythonKeyErrorについて解説します。

1. KeyErrorとは

KeyErrorPythonの組み込み例外の1つで、 「存在しないキーが指定された」 というエラーです。

このエラーは、主に辞書を使った場合に発生します。

簡単に辞書についておさらいしましょう。

以下のように、辞書の要素は「キーのペア」です。

>>> book = {"title": "沈黙の春", "author": "レイチェル カーソン"}

辞書の要素にはキーを使ってアクセスします。

>>> book["title"]
'沈黙の春'
>>> book["author"]
'レイチェル カーソン'

しかし、このキーの指定を間違えるとKeyErrorが発生します。

2. KeyErrorが発生するケース

では、実際にKeyErrorが発生するコード例をみてみましょう。

>>> book["price"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'price'

こちらは存在しないキー"price"を指定しています。

このように存在しないキーを指定すると、KeyErrorが発生します。

もう1つ例を見てみましょう。

>>> book["authar"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'authar'

こちらは存在するキー"author"を指定したつもりでしたが、よく見るとスペルミスで"authar"となっています。

このように、入力ミスでキーの指定を間違え、KeyErrorが発生する場合もあります。

3. KeyErrorの対応方法

KeyErrorの原因は、存在しないキーを指定したことです。

そのため、KeyErrorが発生したら、正しいキーを指定しているかを確認しましょう。

一見、正しいキーを指定しているように見えても、入力ミスで「1文字だけ違う」ということもあるので気をつけましょう。

4. まとめ

  • KeyErrorは存在しないキーを指定した場合に起きるエラー
  • KeyErrorが発生したら、キーの指定が正しいかを確認する