Loading External DLLs at Runtime

51 views
Skip to first unread message

Ben Green

unread,
Jun 7, 2019, 3:04:06 AM6/7/19
to PyInstaller
The problem:
I have a small program that imports a SWIG module, which imports some DLLs. I need to create an executable for this program that can reference these external DLLs as external DLLs, not by bundling them in the executable.

From what I've read, this doesn't seem to be possible. I've tried a few different solutions from forums and such that changed the DLL path or something, and I've tried changing sys.path and os.environ["PATH"], but none of these seem to help the SWIG module find the external DLLs. I can get the program to run just fine if I include the DLLs in the executable, but that isn't the desired behavior.

Does anyone know if there's a way to get PyInstaller to do this?

Eric Fahlgren

unread,
Jun 9, 2019, 9:21:15 AM6/9/19
to pyins...@googlegroups.com
Ben, I think we're doing exactly that in our code.  Exactly when are you setting PATH?  Do you use the runtime_hooks in your .spec file to point to a boot file, so it happens as part of initialization of the product exe?

XXX.spec contains (among all the other stuff):
analyzed = Analysis(
    scripts                 = [path.join(XXX_ROOT, 'XXX/main.py')],
    runtime_hooks           = [path.join(XXX_ROOT, 'install/XXX_boot.py')],
...

Then in install/XXX_boot.py we have (obviously Windows-specific):

os.environ['OUR_PRODUCT_INSTALL_DIR'] = 'something'
os.environ['PATH'] = r'%OUR_PRODUCT_INSTALL_DIR_VAR%\bin;' + os.environ['PATH']

--
You received this message because you are subscribed to the Google Groups "PyInstaller" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyinstaller...@googlegroups.com.
To post to this group, send email to pyins...@googlegroups.com.
Visit this group at https://groups.google.com/group/pyinstaller.
To view this discussion on the web visit https://groups.google.com/d/msgid/pyinstaller/b816bd6d-cf3c-4056-8e0c-d06413d2cf75%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Ben Green

unread,
Jun 12, 2019, 9:45:02 AM6/12/19
to PyInstaller
Eric,

I had tested setting the path at the beginning of the main script, but that was unfruitful. I had not thoroughly looked into runtime_hooks, because it didn't seem to be any different than what I was already attempting. Given your suggestion, though, I gave it a shot. I set up a runtime hook to point to a boot script (that only set the path, as you provided in your example), and I got the same behavior. The path includes the directory containing all of the DLLs I'm trying to provide. The only difference is that I didn't set a separate 'OUR_PRODUCT_INSTALL_DIR' environment variable, which doesn't seem like it's necessary, but I could be wrong.

Do you have any further ideas?


On Sunday, June 9, 2019 at 9:21:15 AM UTC-4, Eric Fahlgren wrote:
Ben, I think we're doing exactly that in our code.  Exactly when are you setting PATH?  Do you use the runtime_hooks in your .spec file to point to a boot file, so it happens as part of initialization of the product exe?

XXX.spec contains (among all the other stuff):
analyzed = Analysis(
    scripts                 = [path.join(XXX_ROOT, 'XXX/main.py')],
    runtime_hooks           = [path.join(XXX_ROOT, 'install/XXX_boot.py')],
...

Then in install/XXX_boot.py we have (obviously Windows-specific):

os.environ['OUR_PRODUCT_INSTALL_DIR'] = 'something'
os.environ['PATH'] = r'%OUR_PRODUCT_INSTALL_DIR_VAR%\bin;' + os.environ['PATH']

On Fri, Jun 7, 2019 at 12:04 AM Ben Green <ben....@geckorobotics.com> wrote:
The problem:
I have a small program that imports a SWIG module, which imports some DLLs. I need to create an executable for this program that can reference these external DLLs as external DLLs, not by bundling them in the executable.

From what I've read, this doesn't seem to be possible. I've tried a few different solutions from forums and such that changed the DLL path or something, and I've tried changing sys.path and os.environ["PATH"], but none of these seem to help the SWIG module find the external DLLs. I can get the program to run just fine if I include the DLLs in the executable, but that isn't the desired behavior.

Does anyone know if there's a way to get PyInstaller to do this?

--
You received this message because you are subscribed to the Google Groups "PyInstaller" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyins...@googlegroups.com.

Ben Green

unread,
Jun 12, 2019, 10:27:39 AM6/12/19
to PyInstaller
Eric,

I was setting the path in the main script right before I imported the SWIG module. At your suggestion, I tried using a runtime_hook to point to a boot file, and I set os.environ["PATH"] in the boot file. I still have the same issue.


On Sunday, June 9, 2019 at 9:21:15 AM UTC-4, Eric Fahlgren wrote:
Ben, I think we're doing exactly that in our code.  Exactly when are you setting PATH?  Do you use the runtime_hooks in your .spec file to point to a boot file, so it happens as part of initialization of the product exe?

XXX.spec contains (among all the other stuff):
analyzed = Analysis(
    scripts                 = [path.join(XXX_ROOT, 'XXX/main.py')],
    runtime_hooks           = [path.join(XXX_ROOT, 'install/XXX_boot.py')],
...

Then in install/XXX_boot.py we have (obviously Windows-specific):

os.environ['OUR_PRODUCT_INSTALL_DIR'] = 'something'
os.environ['PATH'] = r'%OUR_PRODUCT_INSTALL_DIR_VAR%\bin;' + os.environ['PATH']

On Fri, Jun 7, 2019 at 12:04 AM Ben Green <ben....@geckorobotics.com> wrote:
The problem:
I have a small program that imports a SWIG module, which imports some DLLs. I need to create an executable for this program that can reference these external DLLs as external DLLs, not by bundling them in the executable.

From what I've read, this doesn't seem to be possible. I've tried a few different solutions from forums and such that changed the DLL path or something, and I've tried changing sys.path and os.environ["PATH"], but none of these seem to help the SWIG module find the external DLLs. I can get the program to run just fine if I include the DLLs in the executable, but that isn't the desired behavior.

Does anyone know if there's a way to get PyInstaller to do this?

--
You received this message because you are subscribed to the Google Groups "PyInstaller" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyins...@googlegroups.com.

Eric Fahlgren

unread,
Jun 13, 2019, 2:53:04 AM6/13/19
to pyins...@googlegroups.com
Sorry, out of ideas. Maybe the PyInstaller dll loader is ignoring the modifications to PATH, but then why is it working for me?

To unsubscribe from this group and stop receiving emails from it, send an email to pyinstaller...@googlegroups.com.

To post to this group, send email to pyins...@googlegroups.com.
Visit this group at https://groups.google.com/group/pyinstaller.

Ben Green

unread,
Jun 13, 2019, 1:29:14 PM6/13/19
to PyInstaller
I just figured out the solution. I think PyInstaller was finding some of the DLLs, but not all of them. They likely depended on each other using relative paths, so they worked when I manually included all of them. When I didn't, however, the ones that were included tried to find the others via a relative path, rather than using the PATH environment variable.

Whether or not that was the problem, removing all DLLs (except python36.dll) from the binaries attribute of the Analysis object in the spec file worked. Here's the code that got it to work, located immediately after creating an instance of Analysis and assigning it to `a`.

a.binaries = [b for b in a.binaries if b[0].endswith('python36.dll') or not b[0].endswith('.dll')]
Reply all
Reply to author
Forward
0 new messages