首页 > 解决方案 > Django-ValueError:信号仅在主线程中有效

问题描述

是否有可能在call_commandDjango 的信号内或旁边执行 Django 的代码?

到目前为止,我尝试使用 a来尝试使用基于如下的函数ModelForm更新 a :Model classviews

# models.py
class Foo(models.Model):
    ...
    many = models.ManyToManyField("FooMany")
    
class FooMany(models.Model):
    ...
    many = models.CharField(choices=CHOICE, max_length=2)

现在,每个更新请求都会触发一个信号,该信号旨在tests使用 Django 运行特定的call_command

# signals.py
import ntpath
from my_dir import execute  


@receiver(m2m_changed, sender=Executor.path.through)
def run_test(sender, instance, action,  **kwargs):
    files = instance.path.all()
    base = [ntpath.basename(str(f)) for f in files]
    for file in base:
        execute(file)  # execute function comes next
        
        
# my_dir.py
def execute(file):
    with open("executor/results/output", "w") as FILE:
        call_command("test", f"executor.tests.{file}", verbosity=3, interactive=False, stdout=FILE)

完整回溯

Traceback (most recent call last):
  File "/Users/olumide/dev/test_executor/lib/python3.7/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/Users/olumide/dev/test_executor/lib/python3.7/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/olumide/dev/test_executor/src/executor/views.py", line 14, in execute_test
    form.save()
  File "/Users/olumide/dev/test_executor/lib/python3.7/site-packages/django/forms/models.py", line 461, in save
    self._save_m2m()
  File "/Users/olumide/dev/test_executor/lib/python3.7/site-packages/django/forms/models.py", line 443, in _save_m2m
    f.save_form_data(self.instance, cleaned_data[f.name])
  File "/Users/olumide/dev/test_executor/lib/python3.7/site-packages/django/db/models/fields/related.py", line 1670, in save_form_data
    getattr(instance, self.attname).set(data)
  File "/Users/olumide/dev/test_executor/lib/python3.7/site-packages/django/db/models/fields/related_descriptors.py", line 1015, in set
    self.add(*new_objs, through_defaults=through_defaults)
  File "/Users/olumide/dev/test_executor/lib/python3.7/site-packages/django/db/models/fields/related_descriptors.py", line 952, in add
    through_defaults=through_defaults,
  File "/Users/olumide/dev/test_executor/lib/python3.7/site-packages/django/db/models/fields/related_descriptors.py", line 1162, in _add_items
    model=self.model, pk_set=missing_target_ids, using=db,
  File "/Users/olumide/dev/test_executor/lib/python3.7/site-packages/django/dispatch/dispatcher.py", line 179, in send
    for receiver in self._live_receivers(sender)
  File "/Users/olumide/dev/test_executor/lib/python3.7/site-packages/django/dispatch/dispatcher.py", line 179, in <listcomp>
    for receiver in self._live_receivers(sender)
  File "/Users/olumide/dev/test_executor/src/executor/models.py", line 36, in execute_test
    main(file)
  File "/Users/olumide/dev/test_executor/src/executor/tests/execute.py", line 8, in main
    execute()
  File "/Users/olumide/dev/test_executor/src/executor/tests/execute.py", line 7, in execute
    call_command("test", f"executor.tests.{test_file}", verbosity=3, interactive=False, stderr=FILE)
  File "/Users/olumide/dev/test_executor/lib/python3.7/site-packages/django/core/management/__init__.py", line 168, in call_command
    return command.execute(*args, **defaults)
  File "/Users/olumide/dev/test_executor/lib/python3.7/site-packages/django/core/management/base.py", line 371, in execute
    output = self.handle(*args, **options)
  File "/Users/olumide/dev/test_executor/lib/python3.7/site-packages/django/core/management/commands/test.py", line 53, in handle
    failures = test_runner.run_tests(test_labels)
  File "/Users/olumide/dev/test_executor/lib/python3.7/site-packages/django/test/runner.py", line 692, in run_tests
    self.setup_test_environment()
  File "/Users/olumide/dev/test_executor/lib/python3.7/site-packages/django/test/runner.py", line 528, in setup_test_environment
    unittest.installHandler()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/signals.py", line 54, in installHandler
    signal.signal(signal.SIGINT, _interrupt_handler)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/signal.py", line 47, in signal
    handler = _signal.signal(_enum_to_int(signalnum), _enum_to_int(handler))
ValueError: signal only works in main thread

但是,这些都会产生服务器500错误。进一步的调查产生了一个ValueError: 信号只在主线程中工作,我问是否可以这样做,如果不能,你能建议一种不同的方法。谢谢你。

标签: pythondjango

解决方案


推荐阅读