<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>psycopg2Python Tech</title>
	<atom:link href="https://tech.nkhn37.net/category/python/python-libraries/psycopg2/feed/" rel="self" type="application/rss+xml" />
	<link>https://tech.nkhn37.net</link>
	<description>Python学習サイト</description>
	<lastBuildDate>Sun, 11 Jan 2026 08:10:24 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.4</generator>

<image>
	<url>https://tech.nkhn37.net/wp-content/uploads/2021/01/cropped-lion-normal-clear-1-32x32.png</url>
	<title>psycopg2Python Tech</title>
	<link>https://tech.nkhn37.net</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>【Python】psycopg2を用いたPostgreSQLデータベースへのアクセス方法</title>
		<link>https://tech.nkhn37.net/python-psycopg2-postgresql-dbaccess/</link>
					<comments>https://tech.nkhn37.net/python-psycopg2-postgresql-dbaccess/#respond</comments>
		
		<dc:creator><![CDATA[naoki-hn]]></dc:creator>
		<pubDate>Sun, 10 Apr 2022 20:00:00 +0000</pubDate>
				<category><![CDATA[psycopg2]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[threadconnectionpool]]></category>
		<category><![CDATA[コンテキストマネージャー]]></category>
		<category><![CDATA[接続プール]]></category>
		<guid isPermaLink="false">https://tech.nkhn37.net/?p=3478</guid>

					<description><![CDATA[Pythonでpsycopg2を用いてPostgreSQLデータベースへアクセスする方法について解説します。 psycopg2を用いたPostgreSQLアクセス PostgreSQLは、オープンソースのリレーショナルデ [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Pythonで<span class="marker"><strong><code>psycopg2</code></strong></span>を用いてPostgreSQLデータベースへアクセスする方法について解説します。</p>



<h2 class="wp-block-heading jinr-heading d--bold">psycopg2を用いたPostgreSQLアクセス</h2>



<p class="wp-block-paragraph">PostgreSQLは、オープンソースのリレーショナルデータベース(RDB)です。コミュニティによる強力なサポートと継続的な開発により、企業レベルのアプリケーションを含めて世界中で広く利用されています。信頼性や柔軟性が高く、オープンソースであることも多くの開発者に選ばれている理由です。</p>



<p class="wp-block-paragraph">PythonでPostgreSQLのデータベースへアクセスするには、<span class="marker"><strong><code>psycopg2</code></strong></span>モジュールが使用できます。<code>psycopg2</code>は、多くのプロジェクトやアプリケーションで使用されていることから実績が広く認められており、デファクトスタンダードの位置づけにあります。</p>



<p class="wp-block-paragraph">本記事では、<span class="marker"><strong><code>psycopg2</code>を用いてPostgreSQLデータベースへアクセスする方法</strong></span>について説明します。具体的には、<code>psycopg2</code>を用いてPostgreSQLへアクセスするためのクラスを作成し、データベースへアクセスするプログラムを作成します。なお、本記事で紹介するクラスは、コンテキストマネージャーや接続プールにも対応します。</p>



<h3 class="wp-block-heading jinr-heading d--bold">psycopg2のインストール</h3>



<p class="wp-block-paragraph"><code>psycopg2</code>を使用するには、以下のコマンドを用いてpipでインストールを行ってください。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">pip install psycopg2</pre>



<p class="wp-block-paragraph">pipインストールが完了すれば、psycopg2を用いてPostgreSQLへアクセスするための準備ができます。</p>



<h3 class="wp-block-heading jinr-heading d--bold">サンプルプログラムの前提条件</h3>



<p class="wp-block-paragraph">本記事では、PostgreSQLのインストール自体については説明を省略します。以降で紹介するサンプルプログラムを実行するにあたっての前提条件は以下とします。</p>



<section class="wp-block-jinr-blocks-simplebox b--jinr-block-container"><div class="b--jinr-block b--jinr-box d--simple-box1  "><div class="c--simple-box-inner">
<ol class="wp-block-list jinr-list">
<li>PostgreSQLがローカルPCにインストールされているものとする。</li>



<li>DB「test」、スキーマ「work」が作成されているものとする。</li>



<li>ユーザー「test」が作成されており、パスワードは「PAssw0rd」とする。また、workスキーマに対して適切に権限が設定されているものとする。（<code>GRANT ALL ON SCHEMA work TO test;</code>）</li>
</ol>
</div></div></section>



<p class="wp-block-paragraph">以降では、設定ファイルの記載も含めて紹介しています。ご利用の環境に合わせて設定ファイルやプログラムは修正して動作させることも可能です。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--heading-iconbox1 ">
			<div class="a--heading-iconbox-title">
			<div class="a--iconbox-title-icon"><i class="jif jin-ifont-caution" aria-hidden="true"></i></div>
			<div class="a--iconbox-title-text">注意点</div>
			</div>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph">今回は、<code>psycopg2</code> の使用方法に焦点を当てるため細かな例外処理を省略していますのでご注意ください。実際のアプリケーションの利用では、例外処理を十分に考慮する必要があります</p>
</div>
		</div></section>



<h3 class="wp-block-heading jinr-heading d--bold">psycopg2を用いたPostgreSQLアクセスクラス</h3>



<p class="wp-block-paragraph"><code>psycopg2</code>を用いてPostgreSQLデータベースへアクセスするためのクラスを作成します。設定ファイルおよびサンプルプログラムをまず紹介します。具体的な詳細については以降で説明していきます。</p>



<p class="wp-block-paragraph"><strong>【dbconfig.ini】</strong>DBアクセス設定ファイル</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">[POSTGRESQL_DB_SERVER]
host = localhost
port = 5432
dbname = test
user = test
password = PAssw0rd
[POOL]
minconn = 1
maxconn = 10</pre>



<p class="wp-block-paragraph"><strong>【db_connect_postgresql.py】</strong>DBアクセス用クラス</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import configparser

import psycopg2
import psycopg2.extras
from psycopg2 import pool


class DbConnectPostgres:
    # 接続プール
    connection_pool = None

    @classmethod
    def initialize_connection_pool(cls, config_file="./dbconfig.ini") -> None:
        """接続プールの初期化

        Args:
            config_file: 設定ファイルパス

        Returns:
            None
        """
        if cls.connection_pool is None:
            # コンフィグファイルからデータを取得
            config_db = configparser.ConfigParser()
            config_db.read(config_file)

            # 接続情報の取得
            host = config_db["POSTGRESQL_DB_SERVER"]["host"]
            port = config_db["POSTGRESQL_DB_SERVER"]["port"]
            dbname = config_db["POSTGRESQL_DB_SERVER"]["dbname"]
            user = config_db["POSTGRESQL_DB_SERVER"]["user"]
            password = config_db["POSTGRESQL_DB_SERVER"]["password"]
            # プール設定の取得
            minconn = int(config_db["POOL"]["minconn"])
            maxconn = int(config_db["POOL"]["maxconn"])

            # 接続プールを初期化
            cls.connection_pool = pool.ThreadedConnectionPool(
                minconn=minconn,
                maxconn=maxconn,
                host=host,
                port=port,
                dbname=dbname,
                user=user,
                password=password,
            )

    @classmethod
    def close_connection_pool(cls):
        """接続プールをクローズする"""
        if cls.connection_pool:
            cls.connection_pool.closeall()
            cls.connection_pool = None

    def __init__(self) -> None:
        """コンストラクタ"""
        # コネクションとカーソル
        self.conn = None
        self.cursor = None

    def connect(self) -> None:
        """DB接続"""
        if self.connection_pool is None:
            raise Exception("接続プールが初期化されていません")

        # 接続プールからコネクションを取得
        self.conn = self.connection_pool.getconn()
        # カーソルを取得
        self.cursor = self.conn.cursor(
            cursor_factory=psycopg2.extras.DictCursor
        )

    def close(self) -> None:
        """DBクローズ"""
        if self.cursor:
            # カーソルをクローズする
            self.cursor.close()
            self.cursor = None
        if self.conn:
            # 接続をプールに返却する
            self.connection_pool.putconn(self.conn)
            self.conn = None

    def __enter__(self):
        # DB接続
        self.connect()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type:
            # 例外発生時はロールバック
            self.rollback()
            raise
        else:
            # 例外がなければコミット
            self.commit()

        # DBクローズ
        self.close()

    def execute_non_query(self, sql: str, bind_var: tuple = None) -> None:
        """CREATE/INSERT/UPDATE/DELETEのSQL実行メソッド

        Args:
            sql: 実行SQL
            bind_var: バインド変数

        Returns:
            None
        """
        # SQLの実行
        if bind_var:
            # バインド変数がある場合は指定して実行
            self.cursor.execute(sql, bind_var)
        else:
            self.cursor.execute(sql)

    def execute_query(
        self, sql: str, bind_var: tuple = None, count: int = 0
    ) -> list[psycopg2.extras.DictRow]:
        """SELECTのSQL実行メソッド

        Args:
            sql: 実行SQL
            bind_var: バインド変数
            count: データ取得件数

        Returns:
            結果リスト
        """
        # SQLの実行
        if bind_var:
            # バインド変数がある場合は指定して実行
            self.cursor.execute(sql, bind_var)
        else:
            self.cursor.execute(sql)

        if count == 0:
            rows = self.cursor.fetchall()
        else:
            # 件数指定がある場合はその件数分を取得する
            rows = self.cursor.fetchmany(count)

        return rows

    def commit(self) -> None:
        """コミット"""
        self.conn.commit()

    def rollback(self) -> None:
        """ロールバック"""
        self.conn.rollback()</pre>



<h4 class="wp-block-heading jinr-heading d--bold">サンプルコードの詳細説明</h4>



<h5 class="wp-block-heading jinr-heading d--bold">DB接続設定ファイル dbconfig.ini</h5>



<p class="wp-block-paragraph">データベース(DB)へアクセスする際には、接続のための設定情報が必要です。DBの設定情報は、DBアクセス設定ファイルとして<code>dbconfig.ini</code>として用意します。</p>



<p class="wp-block-paragraph">このファイルは、以降で紹介するプログラム内で<code>configparser</code>モジュールを用いて内容を取得します。<code>configparser</code>の使用方法については「<a href="https://tech.nkhn37.net/python-configparser-basic/" target="_blank" rel="noreferrer noopener">configparserによる設定ファイル管理</a>」にまとめていますので参考にしてください。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">[POSTGRESQL_DB_SERVER]
host = localhost
port = 5432
dbname = test
user = test
password = PAssw0rd
[POOL]
minconn = 1
maxconn = 10</pre>



<p class="wp-block-paragraph">設定ファイルには、以下の情報を記載しています。</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>設定値</th><th>概要</th></tr></thead><tbody><tr><td><code>host</code></td><td>具体的なサーバーのホスト名やIPアドレスを記載します。今回はローカルPCを使うため<code>localhost</code>としています。</td></tr><tr><td><code>port</code></td><td>PostgreSQLへアクセスするためのポートです。PostgreSQLではデフォルトで<code>5432</code>が使用されます。お使いの環境で変更している場合は修正が必要です。</td></tr><tr><td><code>dbname</code></td><td>アクセスするデータベース名を記載します。</td></tr><tr><td><code>user</code></td><td>アクセスするユーザーを記載します。</td></tr><tr><td><code>password</code></td><td>アクセス時のパスワードを記載します。</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">以下の項目については、データベースへの接続プールに関する設定項目です。</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>設定値</th><th>概要</th></tr></thead><tbody><tr><td><code>minconn</code></td><td>接続プールにおける最小コネクション数を表します。</td></tr><tr><td><code>maxconn</code></td><td>接続プールにおける最大コネクション数を表します。</td></tr></tbody></table></figure>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--heading-iconbox1 ">
			<div class="a--heading-iconbox-title">
			<div class="a--iconbox-title-icon"><i class="jif jin-ifont-caution" aria-hidden="true"></i></div>
			<div class="a--iconbox-title-text">注意点</div>
			</div>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph">今回は簡単のためパスワードは平文のまま記載していますが、セキュリティ上適切ではありません。実際には暗号化等を考慮する必要がある点に注意してください。</p>
</div>
		</div></section>



<h5 class="wp-block-heading jinr-heading d--bold">DBアクセス用クラス DbConnectPostgres</h5>



<p class="wp-block-paragraph">DBアクセス用のクラスとして<code>DbConnectPostgres</code>というクラスを定義しています。このクラスをDBを使用するプログラムから呼び出すことでPostgreSQLへ簡単にアクセスできます。</p>



<p class="wp-block-paragraph">また、コンテキストマネージャーに対応させることでwith句を用いた資源管理ができるようにしています。コンテキストマネージャーについては「<a href="https://tech.nkhn37.net/python-context-manager-basic/" target="_blank" rel="noreferrer noopener">コンテキストマネージャーの基本</a>」でまとめているので参考にしてください。</p>



<p class="wp-block-paragraph">定義メソッドの概要は以下になります。</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>メソッド名</th><th>概要</th></tr></thead><tbody><tr><td><code>initialize_connection_pool</code></td><td>接続プールを作成する初期化メソッドです。設定ファイルから接続状況を読み込み、接続プールを作成します。<br>このメソッドは<code>classmethod</code>として定義し、アプリケーション起動時に呼び出します。</td></tr><tr><td><code>close_connection_pool</code></td><td>接続プールをクローズするメソッドです。<br>このメソッドは<code>classmethod</code>として定義し、アプリケーション終了時に呼び出します。</td></tr><tr><td><code>__init__</code></td><td><code>DbConnectPostgres</code>クラスのコンストラクタです。</td></tr><tr><td><code>connect</code></td><td>接続プールからコネクションを取得し、カーソルの作成を行います。</td></tr><tr><td><code>close</code></td><td>データベースのクローズ処理を行います。コネクションは、接続プールへ返却します。</td></tr><tr><td><code>__enter__</code></td><td><code>with</code>句を実行する際に呼び出されるコンテキストマネージャーのメソッドです。<br><code>connect</code>メソッドを呼び出すことでDB接続を行い、戻り値を<code>as</code>で指定された変数に反映します。</td></tr><tr><td><code>__exit__</code></td><td><code>with</code>句を抜ける時に呼び出されるコンテキストマネージャーのメソッドです。例外が発生した場合には、<code>exc_type</code>、<code>exc_val</code>、<code>exc_tb</code>に例外情報が渡されます。<br>例外発生時はロールバックし、例外がなければコミットを行ったうえで、DB接続をクローズします。</td></tr><tr><td><code>execute_non_query</code></td><td><code>CREATE</code>/<code>INSERT</code>/<code>UPDATE</code>/<code>DELETE</code>処理用のSQL実行メソッドです。SQL文と必要に応じてバインド変数を渡して処理を実行します。</td></tr><tr><td><code>execute_query</code></td><td><code>SELECT</code>処理用のSQL実行メソッドです。返却値としては辞書のリストを返します。SQL文と必要に応じてバインド変数、データ取得件数を渡して処理を実行します。</td></tr><tr><td><code>commit</code></td><td>コミットして変更内容を確定します。</td></tr><tr><td><code>rollback</code></td><td>ロールバックして変更内容を破棄します。</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">それぞれのメソッドのポイントについて以降で解説していきます。</p>



<p class="wp-block-paragraph"><strong>接続プールの初期化：<code>initialize_connection_pool</code></strong></p>



<p class="wp-block-paragraph"><code>initialize_connection_pool</code>は、接続プールの初期化を行います。初期化の際には、設定ファイルからDBの接続情報と接続プールの設定値を取得します。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">    # 接続プール
    connection_pool = None

    @classmethod
    def initialize_connection_pool(cls, config_file="./dbconfig.ini") -> None:
        """接続プールの初期化

        Args:
            config_file: 設定ファイルパス

        Returns:
            None
        """
        if cls.connection_pool is None:
            # コンフィグファイルからデータを取得
            config_db = configparser.ConfigParser()
            config_db.read(config_file)

            # 接続情報の取得
            host = config_db["POSTGRESQL_DB_SERVER"]["host"]
            port = config_db["POSTGRESQL_DB_SERVER"]["port"]
            dbname = config_db["POSTGRESQL_DB_SERVER"]["dbname"]
            user = config_db["POSTGRESQL_DB_SERVER"]["user"]
            password = config_db["POSTGRESQL_DB_SERVER"]["password"]
            # プール設定の取得
            minconn = int(config_db["POOL"]["minconn"])
            maxconn = int(config_db["POOL"]["maxconn"])

            # 接続プールを初期化
            cls.connection_pool = pool.ThreadedConnectionPool(
                minconn=minconn,
                maxconn=maxconn,
                host=host,
                port=port,
                dbname=dbname,
                user=user,
                password=password,
            )</pre>



<p class="wp-block-paragraph"><strong><code>initialize_connection_pool</code></strong>は、<code>@classmethod</code>としてクラスメソッドとして定義し、アプリケーション起動時に1度呼び出します。コンストラクタ(<code>__init__</code>)で定義しないのはインスタンス化のたびに接続プールを作成する必要はないためです。</p>



<p class="wp-block-paragraph">接続プールを作成するには「<code>from psycopg2 import pool</code>」というようにインポートが必要であることに注意してください。<span class="marker"><strong><code>pool.ThreadConnectionPool</code></strong></span>によりマルチスレッドに対応可能な接続プールを生成できます。</p>



<p class="wp-block-paragraph">なお、<code>minconn</code>は最小接続数、<code>maxconn</code>は最大接続数を表しており、今回の設定ファイルでは、<code>minconn=1</code>、<code>maxconn=10</code>としているので、最大10のコネクションを使用することが可能です。</p>



<p class="wp-block-paragraph"><strong>接続プールのクローズ：<code>close_connection_pool</code></strong></p>



<p class="wp-block-paragraph">接続プールについては、アプリケーションで不要になったときに<code>close_connection_pool</code>を使用してクローズします。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">    @classmethod
    def close_connection_pool(cls):
        """接続プールをクローズする"""
        if cls.connection_pool:
            cls.connection_pool.closeall()
            cls.connection_pool = None</pre>



<p class="wp-block-paragraph">接続プールをクローズする際には<span class="marker"><strong><code>closeall</code></strong></span>メソッドを使用して、すべての接続をクローズします。<code>connection_pool</code>に<code>None</code>を設定することは必須ではありませんが、ガーベージコレクションの対象となることを示すために<code>None</code>を設定しています。</p>



<p class="wp-block-paragraph"><strong>コンストラクタ：<code>__init__</code></strong></p>



<p class="wp-block-paragraph">コンストラクタ(<code>__init__</code>)では、DBへの接続インスタンスごとにコネクションとカーソルを用意しておきます。具体的なコネクション取得やカーソル生成は、以降の<code>connect</code>メソッドで行います。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">    def __init__(self) -> None:
        """コンストラクタ"""
        # コネクションとカーソル
        self.conn = None
        self.cursor = None</pre>



<p class="wp-block-paragraph"><strong>DB接続：<code>connect</code></strong></p>



<p class="wp-block-paragraph"><code>connect</code>メソッドでは、接続プールからコネクションを取得して、カーソルを用意します。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">    def connect(self) -> None:
        """DB接続"""
        if self.connection_pool is None:
            raise Exception("接続プールが初期化されていません")

        # 接続プールからコネクションを取得
        self.conn = self.connection_pool.getconn()
        # カーソルを取得
        self.cursor = self.conn.cursor(
            cursor_factory=psycopg2.extras.DictCursor
        )</pre>



<p class="wp-block-paragraph">接続のためのコネクションは接続プールから取得します。コネクションを取得する際には、接続プールから「<code>self.connection_pool.getconn()</code>」というように<span class="marker"><strong><code>getconn</code></strong></span>メソッドを使用してコネクションを取得します。カーソルは、取得したコネクションの<span class="marker"><strong><code>cursor</code></strong></span>メソッドを使用することでカーソルが作成できます。</p>



<p class="wp-block-paragraph">デフォルトでは、データの返却値はタプルのリストとなります。カーソルを辞書型で扱えるようにするには、<code>cursor_factory</code>引数に<span class="marker"><strong><code>psycopg2.extras.DictCursor</code></strong></span>を指定することで、データを辞書のリストとして扱うことが可能です。</p>



<p class="wp-block-paragraph"><strong>DBクローズ：<code>close</code></strong></p>



<p class="wp-block-paragraph"><code>close</code>メソッドでは、データベースのクローズ処理を行います。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">    def close(self) -> None:
        """DBクローズ"""
        if self.cursor:
            # カーソルをクローズする
            self.cursor.close()
            self.cursor = None
        if self.conn:
            # 接続をプールに返却する
            self.connection_pool.putconn(self.conn)
            self.conn = None</pre>



<p class="wp-block-paragraph">作成したカーソル(<code>cursor</code>)のクローズ処理を<code>close</code>メソッドにより行います。コネクションについては、接続プールに返却するために<span class="marker"><strong><code>putconn</code></strong></span>メソッドにコネクションを渡します。</p>



<p class="wp-block-paragraph"><code>cursor</code>や<code>conn</code>に<code>None</code>を設定することは必須ではありませんが、ガーベージコレクションの対象となることを示すために<code>None</code>を設定しています。</p>



<p class="wp-block-paragraph"><strong>コンテキストマネージャ：<code>__enter__</code> 及び <code>__exit__</code></strong></p>



<p class="wp-block-paragraph"><code>DbConnectPostgres</code>クラスは、<code>with</code>句を用いて使用できるようにコンテキストマネージャーに対応できるように実装します。コンテキストマネージャーに対応するためには、具体的には、<code>__enter__</code>メソッドと<code>__exit__</code>メソッドの実装が必要です。コンテキストマネージャーについては「<a href="https://tech.nkhn37.net/python-context-manager-basic/" target="_blank" rel="noreferrer noopener">コンテキストマネージャーの基本</a>」でまとめているので参考にしてください。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">    def __enter__(self):
        # DB接続
        self.connect()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type:
            # 例外発生時はロールバック
            self.rollback()
            raise
        else:
            # 例外がなければコミット
            self.commit()

        # DBクローズ
        self.close()</pre>



<p class="wp-block-paragraph"><code>__enter__</code>メソッドでは、DB接続を行います。これにより<code>with</code>句に入った際にDB接続を行い、<code>as</code>で指定された変数にDBクラスのインスタンスを設定します。</p>



<p class="wp-block-paragraph"><code>with</code>句を抜ける際には、<code>__exit__</code>メソッドが呼び出されます。この際、例外が発生している場合には、<code>exc_type</code>、<code>exc_val</code>、<code>exc_tb</code>に例外情報が渡されます。例外が発生した場合はロールバックし、再度例外を<code>raise</code>により上位へ送っています。例外がなければコミットし、その後にDBの接続を終了します。</p>



<p class="wp-block-paragraph">このようにコンテキストマネージャーに対応させると<code>with</code>句を一つのトランザクションとして考えることもでき、クローズ処理を忘れることを防止できます。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox5 ">
			<i class="jif jin-ifont-v2speaker" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph"><strong>トランザクションの考え方</strong></p>



<p class="wp-block-paragraph"><code>psycopg2</code> では、SQL を実行したタイミングでトランザクションが開始されますが、自動コミットモードは OFF になっています。そのため、明示的に <code>commit</code> が実行されるまで変更が反映されません。</p>



<p class="wp-block-paragraph">今回紹介しているクラスでは <code>with</code> を抜ける際に <code>commit</code> や <code>rollback</code> が実行されますが、<code>with</code> ブロック内の処理の途中で明示的にコミットしたい場合は適宜 <code>commit</code> メソッドを呼び出す必要があることに注意してください。</p>
</div>
		</div></section>



<p class="wp-block-paragraph"><strong>SQL実行：<code>execute_non_query</code></strong></p>



<p class="wp-block-paragraph">SQL実行用のメソッドとして<code>execute_non_query</code>を用意しています。後述する<code>execute_query</code>との違いは返却値がないことで、<code>CREATE</code>/<code>INSERT</code>/<code>UPDATE</code>/<code>DELETE</code>などのSQLを実行するために使用します。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">    def execute_non_query(self, sql: str, bind_var: tuple = None) -> None:
        """CREATE/INSERT/UPDATE/DELETEのSQL実行メソッド

        Args:
            sql: 実行SQL
            bind_var: バインド変数

        Returns:
            None
        """
        # SQLの実行
        if bind_var:
            # バインド変数がある場合は指定して実行
            self.cursor.execute(sql, bind_var)
        else:
            self.cursor.execute(sql)</pre>



<p class="wp-block-paragraph">SQLを実行するためには、カーソルの<span class="marker"><strong><code>execute</code></strong></span>メソッドに対象のSQLを渡します。また、バインド変数がある場合には引数に指定して実行することができます。</p>



<p class="wp-block-paragraph"><strong>SQL実行：<code>execute_query</code></strong></p>



<p class="wp-block-paragraph">SQL実行用のメソッドとしてもう一つ<code>execute_query</code>を用意しています。上記の<code>execute_non_query</code>との違いは、返却値があることです。<code>SELECT</code>してデータを取得するSQLを実行するために使用します。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">    def execute_query(
        self, sql: str, bind_var: tuple = None, count: int = 0
    ) -> list[psycopg2.extras.DictRow]:
        """SELECTのSQL実行メソッド

        Args:
            sql: 実行SQL
            bind_var: バインド変数
            count: データ取得件数

        Returns:
            結果リスト
        """
        # SQLの実行
        if bind_var:
            # バインド変数がある場合は指定して実行
            self.cursor.execute(sql, bind_var)
        else:
            self.cursor.execute(sql)

        if count == 0:
            rows = self.cursor.fetchall()
        else:
            # 件数指定がある場合はその件数分を取得する
            rows = self.cursor.fetchmany(count)

        return rows</pre>



<p class="wp-block-paragraph">SQLを実行するためには、カーソルの<span class="marker"><strong><code>execute</code></strong></span>メソッドに対象となるSQLを渡します。また、バインド変数がある場合には引数に指定して実行することができます。</p>



<p class="wp-block-paragraph"><code>SELECT</code>結果を全て取得する場合は、<span class="marker"><strong><code>fetchall</code></strong></span>メソッドを使用します。また、件数を指定する場合には、<span class="marker"><strong><code>fetchmany</code></strong></span>メソッドに取得件数を指定します。なお、今回は使用していませんが1件データを取得する<span class="marker"><strong><code>fetchone</code></strong></span>メソッドもあります。</p>



<p class="wp-block-paragraph">返却値は<code>psycopg2.extras.DictRow</code>のリストとなっています。<code>psycopg2.extras.DictRow</code>は、辞書のようにアクセスできる一方で、タプルのように振舞うことも可能なデータ型です。用途によって辞書として扱いたい場合は、<code>dict()</code>によりPythonの辞書型に変換することも可能です。</p>



<p class="wp-block-paragraph"><strong>コミット：<code>commit</code></strong></p>



<p class="wp-block-paragraph">データベースへの変更を確定させるためにはコミットをする必要があります。そのためのメソッドとして<code>commit</code>メソッドを用意しています。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">    def commit(self) -> None:
        """コミット"""
        self.conn.commit()</pre>



<p class="wp-block-paragraph">内部的には、コネクションの<span class="marker"><strong><code>commit</code></strong></span>メソッドを呼び出しているだけです。もし、コミット時に他の処理が必要な場合は追加してください。</p>



<p class="wp-block-paragraph"><strong>ロールバック：<code>rollback</code></strong></p>



<p class="wp-block-paragraph">コミット前のデータベースへの変更を取り消したい場合は、ロールバックしてデータベースの状態を元に戻す必要があります。そのためのメソッドとして<code>rollback</code>メソッドを用意しています。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">    def rollback(self) -> None:
        """ロールバック"""
        self.conn.rollback()</pre>



<p class="wp-block-paragraph">内部的には、コネクションの<span class="marker"><strong><code>rollback</code></strong></span>メソッドを呼び出しているだけです。もし、ロールバック時に他の処理が必要な場合は追加してください。</p>



<h3 class="wp-block-heading jinr-heading d--bold">DBアクセス用クラスの使い方</h3>



<p class="wp-block-paragraph">上記で定義した<code>DbConnectPostgres</code>クラスは、他のプログラムから使用することが可能です。</p>



<p class="wp-block-paragraph">以下の<code>dbaccess_sample.py</code>は、<code>DbConnectPostgres</code>クラスを使用して、テーブルの作成(<code>CREATE TABLE</code>)、データの追加(<code>INSERT</code>)、データ検索(<code>SELECT</code>)の使い方の例を記載しています。それぞれのパートの内容を順に説明します。</p>



<p class="wp-block-paragraph"><strong>【dbaccess_sample.py】</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from db_connect_postgresql import DbConnectPostgres


def main():
    # 接続プールの初期化
    DbConnectPostgres.initialize_connection_pool()

    with DbConnectPostgres() as db:
        # ===== テーブルを作成する
        create_sql = (
            "CREATE TABLE IF NOT EXISTS work.sample_table"
            "("
            "id serial NOT NULL, "
            "str1 character varying(50), "
            "value1 integer, "
            "last_update_datetime timestamp, "
            "PRIMARY KEY (id)"
            ")"
        )
        db.execute_non_query(create_sql)

        # ===== データをINSERTする
        insert_sql = (
            "INSERT INTO work.sample_table "
            "(str1, value1, last_update_datetime) "
            "VALUES(%s, %s, current_timestamp)"
        )
        for i in range(5):
            input_str = f"test_str{i}"
            input_val = 10 * i
            bind = (input_str, input_val)
            db.execute_non_query(insert_sql, bind)

        # ===== データを検索する (全て検索)
        print("===== 全件検索")
        select_sql = "SELECT * FROM work.sample_table"
        select_result = db.execute_query(select_sql)
        print(select_result)

        # ===== 件数を指定して検索する (以下の例は3件)
        print("===== 取得する件数の指定")
        select_sql = "SELECT * FROM work.sample_table"
        select_result = db.execute_query(select_sql, count=3)
        print(select_result)

        # ===== 条件を指定して検索する
        print("===== 条件を指定して実行する")
        select_sql = "SELECT * FROM work.sample_table WHERE value1 > %s"
        print("条件１")
        select_result = db.execute_query(select_sql, (10,))
        print(select_result)
        print("条件２")
        select_result = db.execute_query(select_sql, (30,))
        print(select_result)

    # 接続プールのクローズ
    DbConnectPostgres.close_connection_pool()


if __name__ == "__main__":
    main()</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果例】
===== 全件検索
[[1, 'test_str0', 0, datetime.datetime(2024, 3, 17, 18, 39, 38, 987723)], [2, 'test_str1', 10, datetime.datetime(2024, 3, 17, 18, 39, 38, 987723)], [3, 'test_str2', 20, datetime.datetime(2024, 3, 17, 18, 39, 38, 987723)], [4, 'test_str3', 30, datetime.datetime(2024, 3, 17, 18, 39, 38, 987723)], [5, 'test_str4', 40, datetime.datetime(2024, 3, 17, 18, 39, 38, 987723)]]
===== 取得する件数の指定
[[1, 'test_str0', 0, datetime.datetime(2024, 3, 17, 18, 39, 38, 987723)], [2, 'test_str1', 10, datetime.datetime(2024, 3, 17, 18, 39, 38, 987723)], [3, 'test_str2', 20, datetime.datetime(2024, 3, 17, 18, 39, 38, 987723)]]
===== 条件を指定して実行する
条件１
[[3, 'test_str2', 20, datetime.datetime(2024, 3, 17, 18, 39, 38, 987723)], [4, 'test_str3', 30, datetime.datetime(2024, 3, 17, 18, 39, 38, 987723)], [5, 'test_str4', 40, datetime.datetime(2024, 3, 17, 18, 39, 38, 987723)]]
条件２
[[5, 'test_str4', 40, datetime.datetime(2024, 3, 17, 18, 39, 38, 987723)]]</pre>



<p class="wp-block-paragraph"><strong>モジュールのインポート</strong></p>



<p class="wp-block-paragraph">DBアクセスクラスを使うには、作成したモジュールを以下のようにインポートしてください。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from db_connect_postgresql import DbConnectPostgres</pre>



<p class="wp-block-paragraph"><strong>接続プールの作成とクローズ</strong></p>



<p class="wp-block-paragraph">今回のクラスでは接続プールを使用していますので、使用前に接続プールを初期化する必要があります。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">    # 接続プールの初期化
    DbConnectPostgres.initialize_connection_pool()

    ...(省略)...

    # 接続プールのクローズ
    DbConnectPostgres.close_connection_pool()</pre>



<p class="wp-block-paragraph">上記のようにアプリケーションの最初に接続プールを初期化し、最後には接続プールをクローズするようにしてください。</p>



<p class="wp-block-paragraph"><strong>DBアクセスクラスのインスタンス化</strong></p>



<p class="wp-block-paragraph">クラスはコンテキストマネージャーを使用できるため、以下のように<code>with</code>句を使用してインスタンスを作成することができます。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">    with DbConnectPostgres() as db:
        ...(処理)...</pre>



<p class="wp-block-paragraph"><code>with</code>句に入った際に、<code>connect</code>メソッドにより接続プールからコネクションが取得され、<code>with</code>句を抜けた際に、必要に応じてロールバックやコミットが実行されます。これにより<code>with</code>を一つのトランザクションとして扱うことが可能です。</p>



<p class="wp-block-paragraph">なお、with句を使用しなくてもインスタンス化は可能ですが、その場合は、接続(<code>connect</code>)やクローズ(<code>close</code>)、コミット(<code>commit</code>)やロールバック(<code>rollback</code>)といった処理は自分で適切に呼び出す必要がありますので注意してください。</p>



<p class="wp-block-paragraph"><strong>テーブルの作成（<code>CREATE TABLE</code>）</strong></p>



<p class="wp-block-paragraph"><code>CREATE TABLE</code>でテーブル作成しているのが以下の部分です。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">        # ===== テーブルを作成する
        create_sql = (
            "CREATE TABLE IF NOT EXISTS work.sample_table"
            "("
            "id serial NOT NULL, "
            "str1 character varying(50), "
            "value1 integer, "
            "last_update_datetime timestamp, "
            "PRIMARY KEY (id)"
            ")"
        )
        db.execute_non_query(create_sql)</pre>



<p class="wp-block-paragraph">上記のように<code>CREATE用</code>のSQL文を用意して、<code>execute_non_query</code>メソッドに渡すことでテーブルの作成が可能です。</p>



<p class="wp-block-paragraph"><strong>データの登録（<code>INSERT</code>）</strong></p>



<p class="wp-block-paragraph"><code>INSERT</code>でデータを登録しているのが以下の部分です。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">        # ===== データをINSERTする
        insert_sql = (
            "INSERT INTO work.sample_table "
            "(str1, value1, last_update_datetime) "
            "VALUES(%s, %s, current_timestamp)"
        )
        for i in range(5):
            input_str = f"test_str{i}"
            input_val = 10 * i
            bind = (input_str, input_val)
            db.execute_non_query(insert_sql, bind)</pre>



<p class="wp-block-paragraph">今回の例では、5件データを追加しています。SQLでは、値を埋め込む部分を<code>%s</code>で記載し、バインド変数を用意して渡すことで入力値を変えつつ<code>INSERT</code>しています。</p>



<p class="wp-block-paragraph">なお、今回<code>id</code>は<code>serial</code>で用意されているため自動採番されます。そのため、このプログラムは実行するたびに5件ずつデータが追加されるという動きをします。</p>



<p class="wp-block-paragraph"><strong>データの検索（<code>SELECT</code>）</strong></p>



<p class="wp-block-paragraph"><code>SELECT</code>で登録したデータを検索しているのが以下の部分です。今回は3つほど例を用意しています。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">        # ===== データを検索する (全て検索)
        print("===== 全件検索")
        select_sql = "SELECT * FROM work.sample_table"
        select_result = db.execute_query(select_sql)
        print(select_result)

        # ===== 件数を指定して検索する (以下の例は3件)
        print("===== 取得する件数の指定")
        select_sql = "SELECT * FROM work.sample_table"
        select_result = db.execute_query(select_sql, count=3)
        print(select_result)

        # ===== 条件を指定して検索する
        print("===== 条件を指定して実行する")
        select_sql = "SELECT * FROM work.sample_table WHERE value1 > %s"
        print("条件１")
        select_result = db.execute_query(select_sql, (10,))
        print(select_result)
        print("条件２")
        select_result = db.execute_query(select_sql, (30,))
        print(select_result)</pre>



<p class="wp-block-paragraph">全件検索する場合には「<code>SELECT *</code>」で検索すれば情報を取得できます。また、<code>count</code>引数に数字を指定すれば全件のうち指定した件数のみ取得できます。</p>



<p class="wp-block-paragraph">条件を指定する場合には、<code>WHERE</code>句に具体的に値を設定したSQLをそのまま渡してもいいですが、上記の例では条件の値を<code>%s</code>として、バインド変数で値を変えながら実行しています。これにより条件に一致するデータのみ検索出来ていることが分かります。</p>



<h2 class="wp-block-heading jinr-heading d--bold">まとめ</h2>



<p class="wp-block-paragraph">Pythonで<span class="marker"><strong><code>psycopg2</code></strong></span>を用いてPostgreSQLデータベースへアクセスする方法について解説しました。</p>



<p class="wp-block-paragraph">PostgreSQLは、オープンソースのリレーショナルデータベース(RDB)で、企業レベルのアプリケーションを含めて世界中で広く利用されています。<code>psycopg2</code>モジュールは、PythonでPostgreSQLへアクセスができるもので、多くのプロジェクトやアプリケーションで使用されていることから、デファクトスタンダードの位置づけにあります。</p>



<p class="wp-block-paragraph">本記事では、PostgreSQLへアクセスするためのクラスを作成し、データベースへアクセスする方法を紹介しました。ぜひ、基本を理解してもらって使いこなしてもらえたらと思います。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox6 ">
			<i class="jif jin-ifont-v2books" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph"><code>psycopg2</code> の公式ドキュメントは<a href="https://www.psycopg.org/docs/" target="_blank" rel="noreferrer noopener">こちら</a>を参考にしてください。</p>
</div>
		</div></section>



<section class="wp-block-jinr-blocks-simplebox b--jinr-block-container"><div class="b--jinr-block b--jinr-box d--heading-box8  "><div class="a--simple-box-title d--bold">ソースコード</div><div class="c--simple-box-inner">
<p class="wp-block-paragraph">上記で紹介しているソースコードについては <a href="https://github.com/nkhn37/python-tech-sample-source/tree/main/python-libraries/psycopg2" target="_blank" rel="noreferrer noopener">GitHub</a> にて公開しています。参考にしていただければと思います。</p>
</div></div></section>


<section class="b--jinr-block b--jinr-blogcard d--blogcard-hover-up d--blogcard-style1 d--blogcard-mysite t--round "><div class="a--blogcard-label ef">あわせて読みたい</div><a class="o--blogcard-link t--round" href="https://tech.nkhn37.net/python-tech-summary-page/"><div class="c--blogcard-image"><img decoding="async" class="a--blogcard-img-src" width="128" height="72" src="https://tech.nkhn37.net/wp-content/uploads/2024/08/Python-Tech-Pythonプログラミングガイド_new1-640x360.jpg" alt="【Python Tech】プログラミングガイド" /></div><div class="a--blogcard-title d--bold">【Python Tech】プログラミングガイド</div></a></section>]]></content:encoded>
					
					<wfw:commentRss>https://tech.nkhn37.net/python-psycopg2-postgresql-dbaccess/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Disk: Enhanced  を使用したページ キャッシュ

Served from: tech.nkhn37.net @ 2026-11-04 07:55:29 by W3 Total Cache
-->