跳至主要内容

使用 psycopg2 在 Python 中管理 PostgreSQL 数据库

了解如何使用 Python 的 psycopg2 包创建、连接并管理 PostgreSQL 数据库。
· 14分钟 阅读

使用 AI 探索

数据几乎是您能想到的每一个数字化应用的核心。从移动应用和电脑游戏到银行工具和自动驾驶汽车,一切都建立在数据之上。那这些数据都存在哪里?答案是数据库。

数据库是一种有组织的结构化数据集合,通常以电子方式存储在计算机系统中。尽管近年来出现了为应对数据量和多样性增长而设计的新型数据库,但世界上仍有相当多的数据存储在所谓的关系型数据库中。关系型数据库将数据存储为预定义的表格集合,表格由行和列组成,并通过一个或多个关系连接。

能够整理并从这些数据库中提取数据,是数据行业中的一项基础技能,且需求日益增长。创建和管理数据库的标准方式是 SQL(结构化查询语言)。SQL 是市场上一些最受欢迎的关系型数据库(如 PostgreSQL、Microsoft SQL Server、MySQL 和 SQLite)的基石。

在本教程中,我们将聚焦于基于 PostgreSQL 的数据库,以及如何使用 Python 来创建、连接和管理它们。SQL 与 Python 的组合是您在数据科学旅程中必须掌握的技能之一。为将 Python 与 PostgreSQL 连接起来,我们将使用 psycopg2 包——Python 中最流行的 PostgreSQL 数据库适配器。准备好挑战了吗?让我们开始吧!

了解 PostgreSQL

PostgreSQL 是一款轻量、免费且开源的关系型数据库。凭借其经过验证的架构、可靠性、数据完整性,以及与 Python、R 等流行编程语言的良好集成,PostgreSQL 深受行业欢迎,被各个规模和地区的公司使用。

PostgreSQL 使用并扩展了 SQL 语言,同时结合了许多功能,能够安全地存储和扩展最复杂的数据工作负载。

要开始使用 PostgreSQL,您需要先在计算机上安装它。在 PostgreSQL 的官方网站,您可以找到适用于不同平台和用例的现成软件包与安装程序,以及源代码归档。

在本教程中,我们将使用 Postgres App,这是一款简单、原生的 macOS 应用,内置启动 PostgreSQL 所需的全部功能。但请注意,其他可用的软件包同样适用,而且运行查询的 PostgreSQL 语法在不同软件包之间是一致的。

如果您想进一步了解 PostgreSQL,请查看我们的PostgreSQL 新手指南以及大量SQL 课程。

了解 psycopg2

要连接到您系统或互联网中已创建的数据库,您需要告诉 Python 如何找到它。换句话说,您需要告知 Python,您感兴趣的数据库是一个 PostgreSQL 数据库。

在 Python 中,您有多种可选方案可供选择。本教程中我们将使用 psycopg2,它可能是最受欢迎的 Python 用 PostgreSQL 数据库适配器。要在您的计算机上正常工作,psycopg2 需要一些前置条件。安装完成后(参见文档了解更多信息),您可以像安装其他 Python 包一样安装 psycopg2:

pip install psycopg2

不过,如果您想更省事地使用 psycopg2,也可以安装 psycopg2-binary,这是该包的独立版本,无需编译器或外部库。对于新用户,推荐采用这种安装方式。

pip install psycopg2-binary

最后,如果您在 Conda 环境中使用 Python,应该通过Anaconda 安装来安装psycopg2:

conda install -c anaconda psycopg2

现在一切就绪,让我们用 psycopg2 来创建您与 PostgreSQL 会话的第一次连接吧!

将 Python 连接到 PostgreSQL

要使用 Python 与 PostgreSQL 数据库交互,我们需要建立一个连接。可通过 psycopg2 的 connect() 函数完成,它会创建一个新的数据库会话并返回一个新的连接实例。

在本教程中,我们将连接到一个名为 “datacamp_courses” 的本地数据库。

conn = psycopg2.connect(database = "datacamp_courses", 
                        user = "datacamp", 
                        host= 'localhost',
                        password = "postgresql_tutorial",
                        port = 5432)

基本连接参数包括:

  • database. 数据库名称。
  • user. 用于认证的用户名。
  • password. 用于认证的密码。
  • host. 数据库服务器地址(在我们的示例中,数据库本地托管,但也可以是 IP 地址)。
  • port. 连接端口号(如未提供,默认为 5432)。

在 PostgreSQL 中创建表

现在是时候在 datacamp_courses 数据库中创建您的第一张表了。我们希望创建一张包含 DataCamp 课程目录中部分课程信息的表。该表的模式如下:

该规范为我们提供了关于表列的相当多信息。表的主键应为 course_id,其数据类型为整数。主键是一种约束,要求该列的值非空且唯一。它使您能够唯一标识表中的特定实例或一组实例。

其余列提供了课程名称、授课教师姓名以及课程主题等信息。

在创建表之前,有必要解释一下您刚创建的连接实例是如何工作的。本质上,连接封装了一个数据库会话,它允许您使用 cursor() 方法执行 SQL 命令和查询,例如 SELECT、INSERT、CREATE、UPDATE 或 DELETE,并使用 commit() 方法将更改持久化。

创建游标实例后,您可以使用 execute() 方法向数据库发送命令,并使用 fetchone()、fetchmany() 或 fetchall() 从表中检索数据。

最后,在完成操作后,务必关闭游标和与数据库的连接。否则,它们会持续占用服务器端资源。您可以使用 close() 方法来关闭。

下面是创建 datacamp_courses 表的代码:

# Open a cursor to perform database operations
cur = conn.cursor()
# Execute a command: create datacamp_courses table
cur.execute("""CREATE TABLE datacamp_courses(
            course_id SERIAL PRIMARY KEY,
            course_name VARCHAR (50) UNIQUE NOT NULL,
            course_instructor VARCHAR (100) NOT NULL,
            topic VARCHAR (20) NOT NULL);
            """)
# Make the changes to the database persistent
conn.commit()
# Close cursor and communication with the database
cur.close()
conn.close()

这是在 PostgreSQL 上创建表的一个非常基础的示例,但实际情况可能复杂得多。如果您想进一步学习如何创建 PostgreSQL 数据库,并探索其结构、数据类型以及如何进行规范化,请查看我们的创建 PostgreSQL 数据库课程。

在 Python 中执行基础 PostgreSQL 查询

datacamp_courses 表已就绪,现在是时候使用 SQL 来执行一些基本查询了!

INSERT

您可能注意到,表中目前还没有任何值。要在 datacamp_courses 表中创建记录,我们需要使用 INSERT 命令。

cur = conn.cursor()

cur.execute("INSERT INTO datacamp_courses(course_name, course_instructor, topic) VALUES('Introduction to SQL','Izzy Weber','Julia')");

cur.execute("INSERT INTO datacamp_courses(course_name, course_instructor, topic) VALUES('Analyzing Survey Data in Python','EbunOluwa Andrew','Python')");

cur.execute("INSERT INTO datacamp_courses(course_name, course_instructor, topic) VALUES('Introduction to ChatGPT','James Chapman','Theory')");

cur.execute("INSERT INTO datacamp_courses(course_name, course_instructor, topic) VALUES('Introduction to Statistics in R','Maggie Matsui','R')");

cur.execute("INSERT INTO datacamp_courses(course_name, course_instructor, topic) VALUES('Hypothesis Testing in Python','James Chapman','Python')");

conn.commit()
cur.close()
conn.close()

生成的表如下所示:

course_id

course_name

course_instructor

topic

1

Introduction to SQL

Izzy Weber

Julia

2

Analyzing Survey Data in Python

EbunOluwa Andrew

Python

3

Introduction to ChatGPT

James Chapman

Theory

4

Introduction to Statistics in R

Maggie Matsui

R

5

Hypothesis Testing in Python

James Chapman

Python

SELECT

在数据科学之旅中,读取 SQL 数据库中的数据可能是您最常做的事情之一。这通常称为 SELECT 查询。现在,让我们来看看 datacamp_courses 表的情况。

我们将调用经典的 SELECT * FROM database_name 语句以读取表中的全部数据。随后,我们使用 fetchall() 方法获取所有可用行。请注意,PostgreSQL 会为 course_id 列自动创建一个数值索引。

cur = conn.cursor()
cur.execute('SELECT * FROM datacamp_courses;')
rows = cur.fetchall()
conn.commit()
conn.close()
for row in rows:
    print(row)
(1, 'Introduction to SQL', 'Izzy Weber', 'Julia')
(2, 'Analyzing Survey Data in Python', 'EbunOluwa Andrew', 'Python')
(3, 'Introduction to ChatGPT', 'James Chapman', 'Theory')
(4, 'Introduction to Statistics in R', 'Maggie Matsui', 'R')
(5, 'Hypothesis Testing in Python', 'James Chapman', 'Python')

UPDATE

数据中经常会出现错误。您可能在上一节中注意到,课程 “Introduction to SQL” 的主题被标记为 Julia。经过核对课程信息,我们发现这是个错误。我们需要将其改为 “SQL”。这可以通过 UPDATE 语句来完成,如下所示:

cur = conn.cursor()
cur.execute("UPDATE datacamp_courses SET topic = 'SQL' WHERE course_name = 'Introduction to SQL';")
conn.commit()
conn.close()

DELETE

最后,您可能希望删除表中的某条记录。例如,让我们删除课程 Introduction to Statistics in R:

cur = conn.cursor()
cur.execute("""DELETE from datacamp_courses WHERE course_name = 'Introduction to Statistics in R'""");
conn.commit()
cur.close()

在 Python 中执行高级 PostgreSQL 查询

在上一节中,我们回顾了最基本的 SQL 查询。但值得学习的内容还有很多。让我们来看看一些更高级的查询。

ORDER BY

假设您想按授课教师的姓名对数据库进行排序。您可以使用 ORDER BY 语句:

cur = conn.cursor()

cur.execute('SELECT * FROM datacamp_courses ORDER BY course_instructor')
rows = cur.fetchall()
for row in rows:
    print(row)
(2, 'Analyzing Survey Data in Python', 'EbunOluwa Andrew', 'Python')
(1, 'Introduction to SQL', 'Izzy Weber', 'SQL')
(3, 'Introduction to ChatGPT', 'James Chapman', 'Theory')
(4, 'Hypothesis Testing in Python', 'James Chapman', 'Python')

GROUP BY

您可能希望在不同数据分组内执行一些聚合函数。例如,您可能想计算不同授课教师所教授课程的数量。可以使用 GROUP BY 来完成此类操作。

cur = conn.cursor()
cur.execute('SELECT course_instructor, COUNT(*) FROM datacamp_courses GROUP BY course_instructor')
rows = cur.fetchall()
for row in rows:
    print(row)
('James Chapman', 2)
('Izzy Weber', 1)
('EbunOluwa Andrew', 1)

JOIN

到目前为止,我们只使用了 datacamp_course 表。然而,只有当您同时使用多张表时,才能真正发挥关系型数据库(如 PostgreSQL)的全部潜力。

组合多张表的“魔法工具”是 JOIN 操作。设想我们的数据库中还有一张名为 programming_languages 的表,包含关于数据科学中最热门编程语言的一些基本信息,包括名称、在 TIOBE 指数中的排名,以及 Datacamp 上关于该语言的课程数量。该表如下所示:

language_id

language_name

course_number

tiobe_ranking

1

SQL

31

8

2

Python

157

1

3

R

132

16

4

Julia

2

33

5

Scala

1

38

假设您想合并这两张表,以同时获得课程信息以及该语言在 TIOBE 指数中的排名。我们将使用 INNER JOIN 来仅获取出现在 datacamp_course 表中的编程语言的信息。

cur = conn.cursor()
cur.execute("""SELECT course_name, course_instructor, topic, tiobe_ranking
FROM datacamp_courses
INNER JOIN programming_languages
ON datacamp_courses.topic = programming_languages.language_name""")
rows = cur.fetchall()
for row in rows:
    print(row)
('Introduction to SQL', 'Izzy Weber', 'SQL', 8)
('Analyzing Survey Data in Python', 'EbunOluwa Andrew', 'Python', 1)
('Hypothesis Testing in Python', 'James Chapman', 'Python', 1)

这只是一个例子,但 SQL 联结的潜力几乎是无限的,因此这是一个必须掌握的主题。我们的课程、教程和速查表将帮助您入门。

SQLAlchemy 入门

Psycopg2 是连接 PostgreSQL 数据库的优秀工具。但如果您需要与其他 SQL 数据库(如 Oracle、MySQL)托管的数据库一起工作呢?在这些场景下,使用能够连接不同类型 SQL 数据库的工具可能更合适。为此,SQLAlchemy 是一个很好的候选。

简单来说,SQLAlchemy 允许用户使用 Python 语言连接数据库,利用面向对象的方式运行 SQL 查询,并优化工作流。

尽管与 psycopg2 相比语法有所不同,但您几乎可以完成同样的事情。下面是一个示例,演示如何创建引擎以连接我们的 datacamp_courses 数据集,并读取 datacap_course 表中的所有数据

import sqlalchemy as db


engine = db.create_engine("postgresql://datacamp@localhost:5432/datacamp_courses")
conn = engine.connect() 
output = conn.execute("SELECT * FROM datacamp_courses")
print(output.fetchall())
conn.close()
[(3, 'Introduction to ChatGPT', 'James Chapman', 'Theory'),
 (5, 'Hypothesis Testing in Python', 'James Chapman', 'Python'),
 (2, 'Analyzing Survey Data in Python', 'EbunOluwa Andrew', 'Python'),
 (1, 'Introduction to SQL', 'Izzy Weber', 'SQL')]

SQLAlchemy 也是一个非常值得学习的工具。想先睹为快其工作方式,请查看我们的 SQLAlchemy 教程。

在 DataCamp DataLab 中使用 PostgreSQL

在 DataCamp,我们致力于让数据科学更简单、更易于每个人获取。这正是我们创建 DataCamp DataLab 的初衷——一款专为数据科学设计的云端笔记本。您可以将 DataCamp DataLab 理解为 Jupyter Notebook 与 Google 文档的结合体,允许用户单独或协同编写代码、分析数据并分享洞见。

将 DataLab 连接到 PostgreSQL(以及其他 SQL 数据库)非常简单。DataLab 允许您安全地连接到数据源,同时还能无缝使用 Python 或 R 继续进行数据分析。您只需按照一个直观的零代码流程创建一个集成,在其中输入您的连接凭据即可。

最后,如果您想尝试集成但手头没有可连接的 PostgreSQL 数据库,您可以使用我们的示例 PostgreSQL 数据库!

对 DataCamp DataLab 感到好奇吗?请查看这篇文章,进一步了解这款新一代数据科学笔记本。

结语

做得很好!在本教程中,您初步了解了 PostgreSQL,并学习了如何借助 psycopg2 包在 Python 中管理数据库。但这仅仅是起点。SQL 是数据科学中使用最广泛的编程语言之一,而且相对容易上手,所以没有理由不学。

幸运的是,Datacamp 已为您准备就绪。以下资源可帮助您熟练掌握 PostgreSQL 以及更广泛的 SQL:

FAQs

psycopg2 和 psycopg2-binary 有什么区别?

psycopg2 是源代码包,要求您的系统安装 C 编译器和 PostgreSQL 客户端库。psycopg2-binary 是预编译版本,包含快速上手所需的一切。它非常适合开发和学习用途,但由于可能存在二进制不兼容,不推荐用于生产环境。

如何在 Python 中处理数据库连接错误?

您可以使用 Python 的 try-except 块来捕获并处理与连接相关的错误。例如:

import psycopg2
from psycopg2 import OperationalError

try:
    conn = psycopg2.connect(
        database="datacamp_courses",
        user="datacamp",
        password="postgresql_tutorial",
        host="localhost",
        port=5432
    )
except OperationalError as e:
    print(f"An error occurred: {e}")

这样可以让您的脚本优雅地失败,甚至在需要时重试连接。

如何连接到远程而非本地的 PostgreSQL 数据库?

要连接到远程 PostgreSQL 数据库,请将 localhost 替换为远程服务器的 IP 地址或域名。请确保:

  • 数据库服务器允许外部连接。
  • 防火墙中已开放正确的端口(通常为 5432)。
  • 您的 PostgreSQL pg_hba.conf 文件已配置为接受远程连接。
我可以使用环境变量安全地存储数据库凭据吗?

是的,将凭据存储为环境变量比硬编码更安全。您可以使用 os.environ 在 Python 中访问它们:

import os
conn = psycopg2.connect(
    database=os.environ["DB_NAME"],
    user=os.environ["DB_USER"],
    password=os.environ["DB_PASSWORD"],
    host=os.environ["DB_HOST"],
    port=os.environ["DB_PORT"]
)

在本地可使用 .env 文件配合 python-dotenv 等工具进行管理。

使用 psycopg2 时如何防止 SQL 注入攻击?

务必使用参数化查询,而不是在插入用户数据时使用字符串格式化:

cur.execute("INSERT INTO datacamp_courses(course_name, course_instructor, topic) VALUES (%s, %s, %s)",
            ('Course Name', 'Instructor', 'Topic'))

这可防止恶意用户将有害的 SQL 代码注入到您的查询中。

如何在 psycopg2 中一次性更新多行?

您可以使用 executemany() 方法高效地插入或更新多行:

courses = [
    ('Course A', 'Instructor A', 'Python'),
    ('Course B', 'Instructor B', 'R')
]
cur.executemany("INSERT INTO datacamp_courses(course_name, course_instructor, topic) VALUES (%s, %s, %s)", courses)
PostgreSQL 提供哪些数据类型?它们如何映射到 Python?

以下是一些常见的 PostgreSQL 数据类型及其在 Python 中的等价类型:

PostgreSQL 类型Python 等价类型
INTEGERint
VARCHAR, TEXTstr
BOOLEANbool
DATE, TIMESTAMPdatetime.date, datetime.datetime
NUMERICdecimal.Decimal
如何使用 Python 将 PostgreSQL 数据导出为 CSV?

您可以将 copy_expert() 方法与 SQL COPY 命令结合使用:

with open('courses.csv', 'w') as f:
    cur.copy_expert("COPY datacamp_courses TO STDOUT WITH CSV HEADER", f)

这对于创建备份或导出数据以供分析非常有用。

我可以在 Jupyter Notebook 中运行这些 Python-PostgreSQL 命令吗?

当然可以!psycopg2 在 Jupyter 中可顺畅使用。只要确保在查询结束后正确关闭数据库连接即可,因为 Jupyter 会话可能保持打开并占用资源。

在 Python 中调试失败的 SQL 查询,最佳方式是什么?

您可以:

  • 在执行前打印查询及其参数。
  • 使用 PostgreSQL 日志以获取更多细节。
  • 通过设置 psycopg2 的 connection.set_isolation_level() 或在使用 SQLAlchemy 接口时启用其 echo 模式来开启日志。
Javier Canales Luna

作者

Javier Canales Luna

我是一名自由职业的数据分析师,与全球各地的公司和组织合作开展数据科学项目。我也担任数据科学讲师,拥有2年以上授课经验。我经常用英语和西班牙语撰写与数据科学相关的文章,其中一些已发表在 DataCamp、Towards Data Science 和 Analytics Vidhya 等知名网站上。作为一名具有政治学与法律背景的数据科学家,我的目标是在公共政策、法律与技术的交汇处开展工作,借助思想的力量推动创新解决方案与叙事,帮助我们应对紧迫挑战,尤其是气候危机。我认为自己是自学成才、不断进步的人,坚定支持跨学科合作。学习新事物永远不嫌晚。

主题