django_dramatiq icon indicating copy to clipboard operation
django_dramatiq copied to clipboard

Executable name for Dramatiq on Windows is "dramatiq.exe"

Open pkimber opened this issue 3 years ago • 4 comments

The _resolve_executable method in django_dramatiq/management/commands/rundramatiq.py will find venv\Scripts\dramatiq, but on Windows it needs to find venv\Scripts\dramatiq.exe

Can we update the code in: https://github.com/Bogdanp/django_dramatiq/commit/4c70775bbdd7b4a6844afeec48ddb58d3bb7275d

pkimber avatar Jun 23 '21 08:06 pkimber

  1. The python path isn't being searched because I am using subprocess.Popen

  2. The old _resolve_executable builds the path to venv\Scripts\dramatiq (as long as sys.executable returns something):

def _resolve_executable(self, exec_name):
    bin_dir = os.path.dirname(sys.executable)
    if bin_dir:
        return os.path.join(bin_dir, exec_name)
    return exec_name

The new version of _resolve_executable only updates the executable_path if the file exists (if os.path.isfile(exec_path)). For Windows, we need to look for dramatiq.exe.

pkimber avatar Jun 23 '21 09:06 pkimber

I solved the issue by adding to the _resolve_executable method in django_dramatiq/django_dramatiq/management/commands/rundramatiq.py:

# fall back to default behaviour (from earlier versions)
return os.path.join(bin_dir, exec_name)

Here is the whole method:

    def _resolve_executable(self, exec_name):
        bin_dir = os.path.dirname(sys.executable)
        if bin_dir:
            for d in [bin_dir, os.path.join(bin_dir, "Scripts")]:
                exec_path = os.path.join(d, exec_name)
                if os.path.isfile(exec_path):
                    return exec_path
            # fall back to default behaviour (from earlier versions)
            # ref https://github.com/Bogdanp/django_dramatiq/issues/109
            return os.path.join(bin_dir, exec_name)
        return exec_name

I tried to write a test, but failed. Would you like me to create a pull request for the method (without tests)?

pkimber avatar Jun 28 '21 11:06 pkimber

I'm confused about why the fallback would fix the problem in this case. exec_name is always either dramatiq or dramatiq-gevent so even with the fallback in place, it sounds like it would resolve to the wrong path. What am I missing?

Bogdanp avatar Aug 08 '21 06:08 Bogdanp

Not sure I am helping, but I wrote a Django management command with two versions of _resolve_executable (_resolve_executable and _resolve_executable_updated):

import os
import sys

from django.core.management.base import BaseCommand


class Command(BaseCommand):
    help = "Dramatiq - process is stopping #5668"

    def _resolve_executable(self, exec_name):
        bin_dir = os.path.dirname(sys.executable)
        if bin_dir:
            for d in [bin_dir, os.path.join(bin_dir, "Scripts")]:
                exec_path = os.path.join(d, exec_name)
                if os.path.isfile(exec_path):
                    return exec_path
        return exec_name

    def _resolve_executable_updated(self, exec_name):
        bin_dir = os.path.dirname(sys.executable)
        if bin_dir:
            for d in [bin_dir, os.path.join(bin_dir, "Scripts")]:
                exec_path = os.path.join(d, exec_name)
                if os.path.isfile(exec_path):
                    return exec_path
            # fall back to default behaviour (from earlier versions)
            # ref https://github.com/Bogdanp/django_dramatiq/issues/109
            return os.path.join(bin_dir, exec_name)
        return exec_name

    def handle(self, *args, **options):
        self.stdout.write(f"{self.help}")
        executable_name = "dramatiq"
        result = self._resolve_executable(executable_name)
        self.stdout.write("_resolve_executable:")
        self.stdout.write(f"{result}")
        result = self._resolve_executable_updated(executable_name)
        self.stdout.write("_resolve_executable_updated:")
        self.stdout.write(f"{result}")
        self.stdout.write(f"{self.help} - Complete")

On my Windows server, the return value is different:

(venv) C:\kb>python manage.py 5668-dramatiq-process-stopping
_resolve_executable:
dramatiq
_resolve_executable_updated:
c:\kb\venv\Scripts\dramatiq 

I am starting Dramatiq using a Windows service (win32serviceutil.ServiceFramework) and Dramatiq will not start unless we have the full path i.e. c:\kb\venv\Scripts\dramatiq.

Sorry... I am not being much help here, but thought I would share.

pkimber avatar Sep 01 '23 09:09 pkimber