You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WSL环境下Alembic与Pytest连接本地PostgreSQL认证失败

解决pytest+Alembic连接PostgreSQL密码认证失败问题

问题现象

在WSL环境下使用pytest结合Alembic连接Docker部署的PostgreSQL时,出现以下密码认证失败错误,即使相同密码可通过pgAdmin正常连接:

sqlalchemy.exc.OperationalError: (psycopg2.OperationalError) connection to server at "localhost" (127.0.0.1), port 5432 failed: FATAL:  password authentication failed for user "testuser"

环境配置信息

Docker部署PostgreSQL命令

docker run -d --rm --name postgres-container -e POSTGRES_USER=testuser -e POSTGRES_PASSWORD=examplepass -p 5432:5432 postgres:latest

pytest.ini配置

[pytest]
verbosity_assertions = 1
env = 
    DB_PASS=examplepass
    DB_USER=testuser
    DB_HOST=localhost
    DB_NAME=testdb
    DB_PORT=5432

conftest.py初始化代码

@pytest.fixture(scope='module')
def connection_string():
    return f'postgresql://{os.getenv("DB_USER")}:{os.getenv("DB_PASS")}@{os.getenv("DB_HOST")}/{os.getenv("DB_NAME")}'

@pytest.fixture(scope='module')
def engine(connection_string):
    logging.info(connection_string)
    engine = create_engine(connection_string)
    logging.info(engine.url)
    return engine

@pytest.fixture(scope='module')
def tables(engine):
    alembic_cfg = AlembicConfig("alembic.ini")
    alembic_cfg.set_main_option('sqlalchemy.url', str(engine.url))
    command.upgrade(alembic_cfg, "head")
    yield
    command.downgrade(alembic_cfg, "base")

@pytest.fixture(scope='module')
def session(engine, tables, context):
    """Returns an sqlalchemy session, and after the test tears down everything properly."""
    connection = engine.connect()
    Session = sessionmaker(bind=connection)
    session = Session()
    # inserts example tables
    insert_into_tables(session, context)
    yield session

test_file.py测试代码

sys.path.append(".")
from sqlalchemy import text

def test_db_setup(session):
    # Try to execute a simple query to check if a table exists
    result_table_exists = session.execute(text("SELECT EXISTS (SELECT FROM information_schema.tables WHERE table_name = 'task')"))

日志输出(确认连接URL正确)

INFO    root:conftest.py:47 postgresql://testuser:examplepass@localhost/testdb
INFO    root:conftest.py:49 postgresql://testuser:***@localhost/testdb

排查与解决方案

1. 解决WSL与Docker的网络映射问题

WSL2的localhost默认不与Windows主机的localhost直接映射,如果你的Docker是在Windows上运行的,WSL内部访问localhost无法连接到Windows上的Docker容器:

  • 方案1:改用Windows主机IP访问:在WSL终端执行cat /etc/resolv.conf,找到nameserver后的IP(通常是192.168.x.x),修改pytest.ini中的DB_HOST为该IP。
  • 方案2:开启Docker的WSL集成:打开Docker Desktop设置 → Resources → WSL Integration,勾选你使用的WSL发行版,重启Docker后即可用localhost访问。
  • 方案3:在WSL内部启动Docker容器:直接在WSL终端执行Docker启动命令,此时localhost可正常指向WSL内部的容器。

2. 确认目标数据库存在

Docker启动Postgres时,默认会创建一个与POSTGRES_USER同名的数据库(即testuser),但你的配置中DB_NAME设为testdb,该数据库默认不存在:

  • 方案1:修改pytest.ini中的DB_NAME为testuser,使用默认创建的数据库。
  • 方案2:启动Docker容器时添加-e POSTGRES_DB=testdb参数,让容器自动创建testdb数据库:
    docker run -d --rm --name postgres-container -e POSTGRES_USER=testuser -e POSTGRES_PASSWORD=examplepass -e POSTGRES_DB=testdb -p 5432:5432 postgres:latest
    

3. 手动验证连接可用性

在WSL终端用psql手动测试连接,排除代码层面问题:

# 替换<HOST>为实际IP或localhost
psql -h <HOST> -U testuser -d testdb

输入密码examplepass,如果能成功连接,说明数据库和网络没问题,需检查代码中是否有其他隐藏问题;如果连接失败,说明网络或数据库配置存在问题。

4. 优化session fixture的资源清理(可选)

虽然不影响认证,但为避免资源泄漏,建议在session fixture的yield后添加清理逻辑:

@pytest.fixture(scope='module')
def session(engine, tables, context):
    """Returns an sqlalchemy session, and after the test tears down everything properly."""
    connection = engine.connect()
    Session = sessionmaker(bind=connection)
    session = Session()
    # inserts example tables
    insert_into_tables(session, context)
    yield session
    # 添加清理逻辑
    session.rollback()
    session.close()
    connection.close()

内容的提问来源于stack exchange,提问作者Zu Jiry

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 05:40:34