如何在后台线程中运行Django runserver以优化测试效率?
需求与问题
我需要在后台运行Django的runserver,配合selenium和pytest开展自动化测试。pytest-django提供的live_server虽有类似功能,但它会在每次测试后清空数据库——这意味着每次测试都要重新创建表、执行迁移,冗余且速度慢到无法接受。
我的核心目标是:只创建一次数据库和测试用户,用selenium登录后运行所有测试,但live_server显然无法实现这点。根据官方文档:
你需要在每次测试开始时重新填充数据库,因为测试之间数据库会被清空
官方没有给出解决方案,于是我转而尝试自行在后台启动Django服务器,试过几种方法但都遇到问题:
方法1:使用线程启动
我编写了如下代码:
import os from pathlib import Path from threading import Thread from django.core.management import call_command from django.core.wsgi import get_wsgi_application def start_server(src): os.chdir(src) os.environ.setdefault('DJANGO_SETTINGS_MODULE', f'{Path(src).name}.settings') os.environ['DB_NAME'] = 'test_db.sqlite3' get_wsgi_application() call_command('migrate') call_command('runserver') def run_server(src): thread = Thread(target=start_server, args=[src], daemon=True) thread.start() if __name__ == '__main__': run_server('/path/to/myproject-root')
但运行时抛出错误:
Traceback (most recent call last): File "/usr/local/Cellar/python@3.11/3.11.2_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/threading.py", line 975, in run self._target(*self._args, **self._kwargs) File "/Users/user/Library/Application Support/JetBrains/PyCharm2022.3/scratches/scratch_3.py", line 15, in start_server call_command('runserver') File "/usr/local/lib/python3.11/site-packages/django/core/management/__init__.py", line 198, in call_command return command.execute(*args, **defaults) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/django/core/management/commands/runserver.py", line 74, in execute super().execute(*args, **options) File "/usr/local/lib/python3.11/site-packages/django/core/management/base.py", line 448, in execute output = self.handle(*args, **options) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/django/core/management/commands/runserver.py", line 111, in handle self.run(**options) File "/usr/local/lib/python3.11/site-packages/django/core/management/commands/runserver.py", line 118, in run autoreload.run_with_reloader(self.inner_run, **options) File "/usr/local/lib/python3.11/site-packages/django/utils/autoreload.py", line 673, in run_with_reloader signal.signal(signal.SIGTERM, lambda *args: sys.exit(0)) File "/usr/local/Cellar/python@3.11/3.11.2_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/signal.py", line 56, in signal handler = _signal.signal(_enum_to_int(signalnum), _enum_to_int(handler)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ValueError: signal only works in main thread of the main interpreter
方法2:改用进程启动
我把线程替换为进程:
process = Process(target=start_server, args=[src], daemon=True)
但发现必须移除daemon=True才能正常运行,可移除后无法在不关闭IDE的情况下终止进程,操作非常不便。
临时尝试:关闭自动重载
回到线程方案,修改call_command为:
call_command('runserver', use_reloader=False)
这次服务器能成功启动,但访问时会返回400错误响应。
内容的提问来源于stack exchange,提问作者nlblack323
相关产品推荐
相关产品推荐

