ahk icon indicating copy to clipboard operation
ahk copied to clipboard

Cannot correctly package mouse templates with py2exe

Open ItsIgnacioPortal opened this issue 4 years ago • 5 comments

I'm trying to make a stand-alone executable of a project I made recently, but when running the generated .exe I get the following error:

Traceback (most recent call last):
  File "TerrariaRainbowChat.py", line 266, in <module>
  File "TerrariaRainbowChat.py", line 260, in main
  File "TerrariaRainbowChat.py", line 125, in keepMovin
  File "ahk\mouse.pyc", line 84, in mouse_position
  File "ahk\mouse.pyc", line 119, in mouse_move
  File "ahk\mouse.pyc", line 103, in _mouse_move
  File "ahk\script.pyc", line 121, in render_template
  File "jinja2\environment.pyc", line 883, in get_template
  File "jinja2\environment.pyc", line 857, in _load_template
  File "jinja2\loaders.pyc", line 115, in load
  File "jinja2\loaders.pyc", line 197, in get_source
jinja2.exceptions.TemplateNotFound: mouse/mouse_move.ahk

I tried fixing it by modifying my setup.py to contain the following:

from distutils.core import setup
import py2exe

ahk_data = r"C:\Users\<REDACTED>\Documents\GitHub\terrariaColorfullChat\python37venv\Lib\site-packages\ahk"

setup(
        console=['TerrariaRainbowChat.py'],
        options = {'py2exe': {'bundle_files': 1, 'compressed': True, 'optimize': 2}},
        zipfile = None,
        data_files = [('ahk', [ahk_data])],
        name='Terraria Colourfull Chat',
        version='1.0.2',
    )

(where "<REDACTED>" is my windows username

But I keep getting the following error when building: error: [Errno 13] Permission denied: 'C:\\Users\\<REDACTED>\\Documents\\GitHub\\terrariaColorfullChat\\python37venv\\Lib\\site-packages\\ahk'

I've tried running it in a CMD as Administrator, while Windows 10 Real-Time Protection is turned off, but to no avail. I'm not completely sure if this issue is py2exe's fault, or this ahk wrapper's fault. My guess is both :( This issue is probably closely related to #46 Any help would be greatly appreciated

ItsIgnacioPortal avatar Nov 03 '20 16:11 ItsIgnacioPortal

Thanks for opening this issue. You're right that this is closely related to #46 -- freezing programs that use jinja templates to exe usually causes this problem. Mainly, this is because these compilers don't know that they need the templates! In principle, what you want is to package the templates inside of your executable.

I believe you're on the right track by adding data, but I'm unsure that adding the entire package directory is the correct approach.

One of the common culprits here is that AHK uses pathing relative to __file__ to find the templates directory. See here. Under pyinstaller and I believe also py2exe, __file__ is undefined.

One possible way to get around this might be subclassing AHK to override how/where AHK looks for its templates. This assumes that you bundled a copy of the templates directory at the root of your application:

from ahk import AHK
from jinja2 import Environment, FileSystemLoader
import sys

FrozenCompatibleAHK(AHK):
    @staticmethod
    def is_frozen():
        """Determine if Python is running frozen as EXE or not"""
        return hasattr(sys, 'frozen')
        
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.is_frozen():
            # https://stackoverflow.com/a/24140734/5747944
            approot = os.path.dirname(os.path.abspath(sys.argv[0]))
            templates_path = os.path.join(approot, 'templates')
            self.env = Environment(loader=FileSystemLoader(templates_path),
                                   autoescape=False, trim_blocks=True)

ahk = FrozenCompatibleAHK()
...

This is untested but should work, in theory.

spyoungtech avatar Nov 03 '20 18:11 spyoungtech

Hi @PinkDev1 have you managed to make any progress with this?

spyoungtech avatar Nov 17 '20 19:11 spyoungtech

Sadly, no. I've tried making py2exe import all of the requiered files recursively, but to no avail. See: py2exe/py2exe#52

For now, I've decided to make AHK functionality opt-in; Whoever decides to try to compile it with that, will have to deal with this :p

ItsIgnacioPortal avatar Nov 18 '20 00:11 ItsIgnacioPortal

Thanks for opening this issue. You're right that this is closely related to #46 -- freezing programs that use jinja templates to exe usually causes this problem. Mainly, this is because these compilers don't know that they need the templates! In principle, what you want is to package the templates inside of your executable.

I believe you're on the right track by adding data, but I'm unsure that adding the entire package directory is the correct approach.

One of the common culprits here is that AHK uses pathing relative to __file__ to find the templates directory. See here. Under pyinstaller and I believe also py2exe, __file__ is undefined.

One possible way to get around this might be subclassing AHK to override how/where AHK looks for its templates. This assumes that you bundled a copy of the templates directory at the root of your application:

from ahk import AHK
from jinja2 import Environment, FileSystemLoader
import sys

FrozenCompatibleAHK(AHK):
    @staticmethod
    def is_frozen():
        """Determine if Python is running frozen as EXE or not"""
        return hasattr(sys, 'frozen')
        
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.is_frozen():
            # https://stackoverflow.com/a/24140734/5747944
            approot = os.path.dirname(os.path.abspath(sys.argv[0]))
            templates_path = os.path.join(approot, 'templates')
            self.env = Environment(loader=FileSystemLoader(templates_path),
                                   autoescape=False, trim_blocks=True)

ahk = FrozenCompatibleAHK()
...

This is untested but should work, in theory.

I tried this as well but my program doesn't really freeze but the error is the same. I'm using pyinstaller but i'm either just looking for something that works (doesn't matter if i have to package things with .exe since i'm already doing that) or that can replace pyinstaller since it has other issues i don't like. (That code doesn't fix my issue btw)

DangerMage avatar Jul 17 '22 00:07 DangerMage

Thanks for opening this issue. You're right that this is closely related to #46 -- freezing programs that use jinja templates to exe usually causes this problem. Mainly, this is because these compilers don't know that they need the templates! In principle, what you want is to package the templates inside of your executable. I believe you're on the right track by adding data, but I'm unsure that adding the entire package directory is the correct approach. One of the common culprits here is that AHK uses pathing relative to __file__ to find the templates directory. See here. Under pyinstaller and I believe also py2exe, __file__ is undefined. One possible way to get around this might be subclassing AHK to override how/where AHK looks for its templates. This assumes that you bundled a copy of the templates directory at the root of your application:

from ahk import AHK
from jinja2 import Environment, FileSystemLoader
import sys

FrozenCompatibleAHK(AHK):
    @staticmethod
    def is_frozen():
        """Determine if Python is running frozen as EXE or not"""
        return hasattr(sys, 'frozen')
        
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.is_frozen():
            # https://stackoverflow.com/a/24140734/5747944
            approot = os.path.dirname(os.path.abspath(sys.argv[0]))
            templates_path = os.path.join(approot, 'templates')
            self.env = Environment(loader=FileSystemLoader(templates_path),
                                   autoescape=False, trim_blocks=True)

ahk = FrozenCompatibleAHK()
...

This is untested but should work, in theory.

I tried this as well but my program doesn't really freeze but the error is the same. I'm using pyinstaller but i'm either just looking for something that works (doesn't matter if i have to package things with .exe since i'm already doing that) or that can replace pyinstaller since it has other issues i don't like. (That code doesn't fix my issue btw)

I fixed it by following this (https://github.com/spyoungtech/ahk/issues/46#issuecomment-721238391)

And then having my friends install autohotkey. (though i pointed the path to my venv and not the main python place)

DangerMage avatar Jul 17 '22 22:07 DangerMage

v1 now features better support for freezing. There are now string constants available as a fallback if template files are not included in the frozen bundle 🎉

spyoungtech avatar May 02 '23 05:05 spyoungtech