Does os.environ.get(“ANKI_LAUNCHER”) always return the correct path to the Anki executable file?

I’m trying to get the path to the Anki executable file for running Anki with subprocess.Popen in add-ons.

  • win:anki.exe, mac:anki.app, linux:anki
  • addon: restart anki, self host server

Previously it could be get with shutil.which(“anki”) or sys.executable but this hack does not seem to work with the new launcher.

For now I was able to get the default anki.exe path, and the last downloaded path from Install_Dir64 on Windows, but I don’t know how to get the path of the currently running Anki yet.

Looking at the code it seems that the new launcher saves the Anki path in os.environ.get(“ANKI_LAUNCHER”) and launched from there. Is it safe to use this path cross-platform for this purpose? (or from aqt.package import launcher_executable)

like this:

import os
import subprocess
anki_exec_path = os.getenv("ANKI_LAUNCHER")
subprocess.Popen([anki_exec_path])

or,

import subprocess
from aqt.package import launcher_executable
anki_exec_path = launcher_executable()
subprocess.Popen([anki_exec_path])
2 Likes

It’s used in the new Upgrade/Downgrade option, so pretty sure it’s the recommended way to get the path now:

1 Like

Thanks for the reply. For anyone looking for the code, I tried writing code like this. (but I’ve only tested it on my Windows so I don’t know if it works on cross-platform.)

  1. If there is a path in the user’s config, use it.
  2. If not, get the path from os.getenv(“ANKI_LAUNCHER”).
  3. If it cannot get it, search for the default path.
import os
import shutil
import platform

from aqt import mw

# get anki path (beta)

def get_anki_exe_path():
    config = mw.addonManager.getConfig(__name__)

    anki_path = None

    # user config
    if config.get("use_custom_anki_path", None):
        anki_path = config.get("custom_anki_path", None)

        if anki_path is not None:
            # linux
            if platform.system() == "Linux":
                if os.path.exists(anki_path):
                    return anki_path
                which_path = shutil.which(anki_path)
                if which_path:
                    return which_path
                print("[AnkiRestart] not found path?")

            # win, mac
            elif os.path.exists(anki_path):
                return anki_path

    # ANKI_LAUNCHER (new launcher)
    anki_path = os.getenv("ANKI_LAUNCHER")
    if anki_path is not None and os.path.exists(anki_path):
        return anki_path

    # default path
    if platform.system() == "Windows":
        anki_path = get_anki_path_win()

    elif platform.system() == "Darwin":
        mac_default_path = '/Applications/Anki.app'
        if os.path.exists(mac_default_path):
            anki_path = mac_default_path

    else: # Linux
        linux_default_path = shutil.which("anki")
        if linux_default_path:
            anki_path = linux_default_path

    return None


# for win
def get_anki_path_win():
    # default path
    local_appdata = os.environ.get("LOCALAPPDATA", "")

    if local_appdata:

        default_path = os.path.join(local_appdata, "Programs", "Anki", "anki.exe")
        if os.path.exists(default_path):
            return default_path

    try: # registry "Install_Dir64"
        import winreg
        with winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Software\Anki") as key:

            install_dir = winreg.QueryValueEx(key, "Install_Dir64")[0]
            registry_path = os.path.join(install_dir, "anki.exe")

            if os.path.exists(registry_path):
                return registry_path

    except Exception as e:
        print(f"[AnkiRestart] Install_Dir64: {e}")
        pass

    return None
1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.