在线程中使用django的call_command出现问题

2 投票
2 回答
3116 浏览
提问于 2025-04-16 08:25

我想在一个线程里执行Django的call_method。以下是示例代码:

import sys
sys.path.append("/my/django/project/path/")
import threading
import time 


# Import my django project configuration settings
from django.core.management import setup_environ
from mydjangoprojectname import settings
setup_environ(settings)

from django.core.management import call_command

class ServerStarter(threading.Thread):
    def __init__(self):
        super(ServerStarter, self).__init__()
        print "ServerStarter instance created"

    def run(self):
        print "Starting Django Server..."
        call_command("runserver", noreload=True)


if __name__ == '__main__':
    starter = ServerStarter()
    starter.start()

------------------------------
OutPut:
ServerStarter instance created
Starting Django Server...
ServerStarter instance created
Starting Django Server...
Validating models...
0 errors found
Django version 1.2.3, using settings 'mydjangoprojectname.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Django服务器正常启动,但ServerStarter被创建了两次
而且这两个ServerStarter的实例都在运行。
如果我在run方法里注释掉call_command("runserver", noreload=True),那么只会
创建一个线程(这正是我想要的)。
提前谢谢你们!

2 个回答

5

我找到了解决办法(Chris Morgan说得对)。这段代码按我想要的方式运行:

import sys
sys.path.append("/my/django/project/path/")
import threading

# Import my django project configuration settings
from django.core.management import setup_environ, ManagementUtility

from mydjangoprojectname import settings
setup_environ(settings)


class ServerStarter(threading.Thread):
    def __init__(self):
        super(ServerStarter, self).__init__()
        print "ServerStarter instance created"

    def run(self):
        print "Starting Django Server..."
        utility = ManagementUtility()
        command = utility.fetch_command('runserver')
        command.execute(use_reloader=False)


if __name__ == '__main__':
    starter = ServerStarter()
    starter.start()
0

我觉得这可能是因为Django内部服务器在重新加载所有模块,这是它的常规操作。你可以试试类似于--noreload的选项,用在call_command上(可能是call_command("runserver", noreload=True),但我不太确定)。

(另外,QThread是通过QApplication.exec_()来启动的;除非你有特别的需求要提前启动,否则我认为你不需要自己去运行starter.start()。)

撰写回答