※ この記事は2024年に公開した「psycopg2」版の記事を、現在の標準ライブラリである psycopg3 に対応させて全面リライトしたものです。URLはそのまま引き継いでいます。
PythonからPostgreSQLに接続できるようになると、「ちゃんと動いた」という小さな達成感があります。
この記事では、PythonからPostgreSQLに接続して、データを保存・取得するところまでを、初心者の方にも分かるように順番に解説します。
むずかしい話は後回しです。まずは「つながった」「保存できた」という成功体験を一緒に作っていきましょう。
この記事でできること
- PythonからPostgreSQLに接続できる
- テーブルを作って、データを保存・取得できる
- パスワードをコードに書かない、安全な管理方法が分かる
- 接続できないときに、エラーメッセージから原因を追える
先に結論
今から始めるなら、ライブラリは psycopg2 ではなく psycopg(第3世代・psycopg3) を選んでください。psycopg2は今もメンテナンスされていますが、新機能の開発はpsycopg3側が中心です。これから書くコードも、すべてpsycopg3で統一します。
この記事はローカル環境での確認をベースにしていますが、コードはあとでVPSなどの環境に移しても、ほぼそのまま使えます。
この記事の前提環境
- OS:Windows(Mac・Linuxでもコードは同じです)
- Python:3.12〜3.14
- PostgreSQL:インストール済みで、起動していること
- エディタ:VS Code
仮想環境(venv)の作り方がまだあいまいな方は、先に環境構築の記事で整えてから戻ってくると、つまずきにくいです。
→ Anacondaを使わずにWindowsでPython環境を作る方法
psycopg2とpsycopg3、何が違うの?
psycopgは、PythonからPostgreSQLを操作するためのライブラリです。役割をひとことで言うと、「PythonとPostgreSQLをつなぐ橋渡し役」 です。
ややこしいのは名前です。第2世代が「psycopg2」、第3世代が「psycopg」という名前で配布されています。
| 項目 | psycopg2(第2世代) | psycopg(第3世代) |
|---|---|---|
| インストール名 | psycopg2-binary | psycopg[binary] |
| importの名前 | import psycopg2 | import psycopg |
| 位置づけ | メンテナンス中心 | 現在の標準。新規開発はこちら |
| 接続の書き方 | 開く・閉じるを自分で書く | with文で安全に開閉できる |
| 結果を辞書で受け取る | 別途設定が必要 | row_factory=dict_row で簡単 |
ネット上にはpsycopg2の記事や書籍が今もたくさん残っているので、「どっちを入れればいいの?」と迷いやすいところです。新しく始める分は、psycopg3で統一しておけば大丈夫です。
SQLそのものにまだ慣れていない場合は、基礎がひと通りまとまった書籍を手元に1冊置いておくと助けになります。
→ SQL 第2版 ゼロからはじめるデータベース操作(Amazon)

準備:データベースとユーザーを作る
接続の前に、PostgreSQL側に「入れ物」を用意します。psqlかpgAdminで、次の2行を実行してください。
CREATE USER sample_user WITH PASSWORD 'sample_password';
CREATE DATABASE sample_db OWNER sample_user;SQLパスワードはあくまで例です。ご自分の環境では別の文字列に変えてください。このあとのコードでも、同じ値を使います。
データベースの持ち主(OWNER)を sample_user にするのがポイントです。PostgreSQL 15以降では、持ち主でないユーザーはテーブルを作れない決まりのため、この指定がないとステップ2で「スキーマ public へのアクセスが拒否されました」という権限エラーになります。
ステップ0:psycopg3をインストールする
仮想環境を有効にした状態で、次を実行します。
pip install "psycopg[binary]"Bashここ、よくある間違いです。 pip install psycopg3 ではインストールできません。第3世代でも配布名は psycopg です。「psycopg2-binaryの後継が psycopg[binary]」と覚えてください。
ステップ1:最小構成で接続を確認する
まずは「つながること」だけを確認します。欲張らないのがコツです。
import psycopg
with psycopg.connect(
host="localhost",
port=5432,
dbname="sample_db",
user="sample_user",
password="sample_password",
) as conn:
with conn.cursor() as cur:
cur.execute("SELECT version();")
row = cur.fetchone()
print(row[0])Python実行して、PostgreSQLのバージョン文字列(PostgreSQL 16.x... のような表示)が出れば、接続は成功です。お疲れさまでした、ここが一番の山場です。
ポイントは2つあります。
with文を使うと、接続やカーソルを閉じ忘れません。これがpsycopg3らしい書き方です- psycopg2のときのように、
cur.close()やconn.close()を自分で書く必要はありません
もしエラーが出たら、慌てずに後半の「接続できないときのチェックポイント」を見てください。エラーメッセージ別に対処をまとめています。
ステップ2:テーブルを作って、保存・取得してみる
接続できたら、今度は実際にデータを扱ってみましょう。「メモ」を保存する、小さなテーブルを作ります。
import os
import psycopg
from psycopg.rows import dict_row
conninfo = (
f"host={os.environ.get('PGHOST', 'localhost')} "
f"port={os.environ.get('PGPORT', '5432')} "
f"dbname={os.environ.get('PGDATABASE', 'sample_db')} "
f"user={os.environ.get('PGUSER', 'sample_user')} "
f"password={os.environ['PGPASSWORD']}"
)
with psycopg.connect(conninfo, row_factory=dict_row) as conn:
with conn.cursor() as cur:
# テーブルがなければ作る
cur.execute(
"""
CREATE TABLE IF NOT EXISTS memos (
id SERIAL PRIMARY KEY,
title TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
"""
)
# メモを1件追加する(値は %s で渡す)
cur.execute(
"INSERT INTO memos (title) VALUES (%s) RETURNING id;",
("はじめてのメモ",),
)
new_id = cur.fetchone()["id"]
print(f"追加したメモのID: {new_id}")
# 保存されたメモを全部取得する
cur.execute("SELECT id, title, created_at FROM memos ORDER BY id;")
for row in cur.fetchall():
print(row)Python実行すると、追加したメモが {'id': 1, 'title': 'はじめてのメモ', 'created_at':...} のような「辞書」の形で表示されます。
ここで大事なのは、次の2点です。
値をSQL文に直接埋め込まない
VALUES (%s) と書いて、値は別に渡すのがpsycopgの作法です。文字列を組み立ててSQL文を作ると、SQLインジェクションというセキュリティ上の問題につながります。最初からこの書き方に慣れておくと、あとで困りません。
結果は辞書で受け取る
row_factory=dict_row を指定すると、結果を「列名:値」の辞書で受け取れます。「3列目はなんのデータだっけ?」と迷うことが減るので、初心者のうちほどおすすめです。
なお、このコードは接続情報を環境変数から読んでいます。実行前に、環境変数 PGPASSWORD にパスワードを設定しておいてください(PowerShellなら $env:PGPASSWORD = "sample_password")。理由は次の節で説明します。
接続情報は、環境変数で管理する
ステップ1のコードは分かりやすさを優先して、パスワードをコードに直接書きました。ただ、実際の運用ではおすすめしません。コードをGitHubなどに上げたとき、パスワードまで一緒に公開されてしまうからです。
考え方はシンプルです。
- パスワードはコードに書かず、環境変数(または
.envファイル+python-dotenv)に置く - コード側は
os.environで読み取るだけにする .envファイルは.gitignoreに入れて、リポジトリには含めない
ステップ2のコードが、まさにその形です。最初はステップ1で接続を確認して、動いたらステップ2の形に寄せていく。この順番が無理がありません。
接続できないときのチェックポイント
うまく接続できない場合、Pythonコードよりも 環境側 に原因があることがほとんどです。エラーメッセージで当たりを付けましょう。
| 表示されるエラー(抜粋) | 原因の見当 | 確認すること |
|---|---|---|
connection refused | PostgreSQLが起動していない/ポートが違う | サービスが起動しているか、ポートが5432か |
password authentication failed | ユーザー名かパスワードが違う | 作成時の値と、コード側の値が一致しているか |
database "sample_db" does not exist | データベースを作っていない | CREATE DATABASE を実行したか |
ModuleNotFoundError: No module named 'psycopg' | インストール先の環境が違う | 仮想環境を有効にしてからインストールしたか |
pip install psycopg3 で失敗する | 配布名の勘違い | 正しくは pip install "psycopg[binary]" |
切り分けのコツは、まずpsqlやpgAdminで直接ログインできるかを確認することです。そちらでつながらなければ原因はPostgreSQL側、つながるのにPythonからだけ失敗するなら、接続情報か仮想環境の問題だと分かります。
エラーのときに「何も表示されずに終わる」のを防ぐなら、こんな書き方もできます。
import psycopg
try:
with psycopg.connect(
dbname="sample_db", user="sample_user", password="sample_password"
) as conn:
print("接続できました")
except psycopg.OperationalError as e:
print("接続できませんでした。PostgreSQLの起動と接続情報を確認してください")
print(f"詳細: {e}")PythonなぜSQLiteではなく、PostgreSQLなのか
Pythonで使えるデータベースには、SQLiteという選択肢もあります。
SQLiteは手軽で、小さなスクリプトや検証用途にはとても便利です。このブログでも、勤怠管理アプリはSQLiteで作りました。
→ Pythonで勤怠管理システムを自作する方法|Flask+SQLiteで最速MVP
ただ、次のような場面ではPostgreSQLの方が扱いやすくなります。
- 複数の環境から同じDBに接続したい
- Webアプリとして使いたい
- データを継続的に蓄積したい
最初はSQLiteで始めて、「育ってきたな」と感じたタイミングでPostgreSQLに移行する。この流れも自然です。
この構成でできること・できないこと
ここまでの構成で、できることは次の通りです。
- PythonスクリプトからDBを操作する
- データの保存・取得を行う
- FlaskなどのWebアプリに発展させる
一方で、次のことはこの段階では考えなくて大丈夫です。
- 高負荷な本番運用
- 複雑なDB設計や最適化
- パフォーマンスチューニング
まずは「PythonからDBに触れる感覚」をつかむことを優先してください。
psycopg2から移行する人へ
すでにpsycopg2で書いたコードがある方は、次だけ押さえれば移行できます。
import psycopg2→import psycopgに変わる- インストールは
psycopg2-binary→psycopg[binary] with psycopg.connect(...) as conn:と書けば、コミットとクローズは自動になる(psycopg2のwithはクローズしなかった点が違います)- SQLのプレースホルダ
%sの書き方は、そのまま使えます
既存コードを無理に全部書き換える必要はありません。新しく書く分からpsycopg3にする、で十分です。
よくある質問
Q. 手元の本や記事がpsycopg2前提でも、読み替えて進められますか?
はい、基本の流れ(接続→カーソル→SQL実行→取得)は同じです。importの名前とインストール名、with文の扱いだけ読み替えれば、ほとんどのサンプルはpsycopg3で動きます。
Q. pip install psycopg3 が失敗するのはなぜですか?
そういう名前の配布パッケージが存在しないからです。第3世代の正式な配布名は psycopg で、インストールは pip install "psycopg[binary]" と指定します。
Q. MacやLinuxでも同じコードで動きますか?
はい、この記事のPythonコードはOSに依存しません。違うのは、環境変数の設定方法やPostgreSQLの起動方法くらいです。
このあと多くの人がつまずくポイント
PythonからPostgreSQLに接続できたあと、多くの人が次に悩みます。
- PCを閉じるとデータベースが止まる
- 別の環境から接続できない
- Webアプリから使いたくなった
これらは、Pythonコードの問題ではありません。「PostgreSQLをどこで動かしているか」という、置き場所の問題 です。
次の一歩:PostgreSQLを安定して動かすには

学習や小さな開発を続けるなら、PostgreSQLが常に起動している環境を1つ用意しておくと楽になります。
Pythonからの接続が安定するので、私はこの用途専用にVPSを1台用意しました。ローカル環境で詰まる時間が減り、Pythonのコードそのものに集中しやすくなりました。
もちろん、「まずは自分のPCだけで試したい」という段階でも、まったく問題ありません。この記事でローカル接続まで確認できれば十分です。その先に進みたくなったときに、環境を切り替えればOKです。
まとめ
- 今から始めるなら、ライブラリは psycopg3(
psycopg[binary]) - 接続できたら、テーブル作成→保存→取得まで一気に試すと感覚がつかめる
- パスワードはコードに直接書かず、環境変数で管理する
- つながらないときは、エラーメッセージから環境側を先に疑う
PythonからPostgreSQLに接続できるようになると、扱えるデータの幅が一気に広がります。
最初はローカル環境でも構いません。ただ、作業が増えてきたら「データベースの置き場所」を見直すだけで、Pythonの扱いやすさは変わります。ここまでできていれば、データベースを扱うための入口はクリアです。あとは、どこで動かし続けるかを選ぶだけです。
