基于 Django 开发 Web API ,并对 PyTorch 模型进行预加载时,通过 runserver 启动 Django 服务的过程中,可能会抛出如下 URLconf 相关的 ImproperlyConfigured 异常:
django.core.exceptions.ImproperlyConfigured: The included URLconf 'webapp.urls' does not appear to have any patterns in it. If you see valid patterns in the file then the issue is probably caused by a circular import.
完整的异常信息如下:
Exception in thread django-main-thread:
Traceback (most recent call last):
File "/home/user/.conda/envs/py36.cuda/site-packages/django/urls/resolvers.py", line 591, in url_patterns
iter(patterns)
TypeError: 'module' object is not iterable
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/user/.conda/envs/py362.cuda/lib/python3.6/threading.py", line 916, in _bootstrap_inner
self.run()
File "/home/user/.conda/envs/py362.cuda/lib/python3.6/threading.py", line 864, in run
self._target(*self._args, **self._kwargs)
File "/home/user/.conda/envs/py36.cuda/site-packages/django/utils/autoreload.py", line 53, in wrapper
fn(*args, **kwargs)
File "/home/user/.conda/envs/py36.cuda/site-packages/django/core/management/commands/runserver.py", line 118, in inner_run
self.check(display_num_errors=True)
File "/home/user/.conda/envs/py36.cuda/site-packages/django/core/management/base.py", line 396, in check
databases=databases,
File "/home/user/.conda/envs/py36.cuda/site-packages/django/core/checks/registry.py", line 70, in run_checks
new_errors = check(app_configs=app_configs, databases=databases)
File "/home/user/.conda/envs/py36.cuda/site-packages/django/core/checks/urls.py", line 40, in check_url_namespaces_unique
all_namespaces = _load_all_namespaces(resolver)
File "/home/user/.conda/envs/py36.cuda/site-packages/django/core/checks/urls.py", line 57, in _load_all_namespaces
url_patterns = getattr(resolver, 'url_patterns', [])
File "/home/user/.conda/envs/py36.cuda/site-packages/django/utils/functional.py", line 48, in __get__
res = instance.__dict__[self.name] = self.func(instance)
File "/home/user/.conda/envs/py36.cuda/site-packages/django/urls/resolvers.py", line 598, in url_patterns
raise ImproperlyConfigured(msg.format(name=self.urlconf_name)) from e
django.core.exceptions.ImproperlyConfigured: The included URLconf 'webapp.urls' does not appear to have any patterns in it. If you see valid patterns in the file then the issue is probably caused by a circular import.
该异常信息指向的是 urls.py 解析失败,导致 Django 服务无法正常启动。但是问题的实际原因可能并不是出自 urls 配置错误。经过反复测试发现,在 Django 主进程启动过程中,真实的错误信息似乎被掩盖了,多种错误都可能导致 Django 主进程抛出以上异常信息,导致错误调试非常困难。
以下列举几种可能的错误:
(1)语法错误(如代码缩进,以下第2个函数名少缩进2个空格)
...
def loadPyTorchModel(self):
self.net = nn.DataParallel(self.net.cuda(), device_ids=[1])
netWeights = torch.load(self.modelWeights)
self.net.load_state_dict(netWeights)
self.net.eval()
def doClassify(self, filepath):
with torch.no_grad():
image = Image.open(filepath).convert('RGB')
image = image.resize((224, 224))
image = self.transformer(image)
...
(2)PyTorch 调用错误(如调用 DataParallel() 后未赋值给原 self.net 变量)
...
def loadPyTorchModel(self):
nn.DataParallel(self.net.cuda(), device_ids=[1])
netWeights = torch.load(self.modelWeights)
self.net.load_state_dict(netWeights)
self.net.eval()
def doClassify(self, filepath):
with torch.no_grad():
image = Image.open(filepath).convert('RGB')
image = image.resize((224, 224))
image = self.transformer(image)
...
(3)文件 IO 错误(如调用上述例子中 doClassify() 但文件路径为空)
class TorchModel(ClassifierWrapper):
def __init__(self):
ClassifierWrapper.__init__(self)
self.loadModelMean()
self.transform()
self.loadPyTorchModel()
self.doClassify('')
...
以上示例使用的 Django 版本为 3.1.2。可以发现以上错误均在 __init__() 执行或调用了存在问题的函数,因此,当 Django 主进程启动时,进行到 TorchModel 预加载后就会抛出本篇开头的异常信息。
暂不清楚为什么真实的错误信息会被掩盖,而只输出 URLconf 相关异常。由于难以调试,目前的替代方案是,先将预加载逻辑包装为一个 Web API 接口,即在 views.py 和 urls.py 中添加一个测试接口进行测试,例如,
# urls.py
...
urlpatterns = [
path('', views.index, name='index'),
path('test.service', views.test, name='test'),
]
...
# views.py
...
def test(request):
mdl = TorchModel()
mdl.doClassify(request.GET['imgpath'])
res = MbResponse("Hello, world at deepmodel")
return HttpResponse(res.toJson())
...



