2

I created a python script that uses pythonnet. The script is in a file named main.py. When I run the script from the command line (simply typing main.py at the Windows command prompt), the imported pythonnet module clr works fine. But when I try to build an exe I get an error saying: No module named clr.

To isolate the cause of this, I have verified that building an executable (in my case a simple Tkinter app) using py2exe works. I only have Python 3.4 installed and have verified that where python points to C:\Python34\python.exe.

The error occurs at executable build time and seems to be triggered by including clr in the section {"includes":["sip","clr"]}} in my setup.py for py2exe. The full traceback is below:

Traceback (most recent call last):
  File "setup.py", line 32, in <module>
    windows = [{'script': "main.py"}],
  File "C:\Python34\lib\distutils\core.py", line 148, in setup
    dist.run_commands()
  File "C:\Python34\lib\distutils\dist.py", line 917, in run_commands
    self.run_command(cmd)
  File "C:\Python34\lib\distutils\dist.py", line 936, in run_command
    cmd_obj.run()
  File "C:\Python34\lib\site-packages\py2exe\distutils_buildexe.py", line 188, i
n run
    self._run()
  File "C:\Python34\lib\site-packages\py2exe\distutils_buildexe.py", line 267, i
n _run
    builder.analyze()
  File "C:\Python34\lib\site-packages\py2exe\runtime.py", line 164, in analyze
    mf.import_hook(modname)
  File "C:\Python34\lib\site-packages\py2exe\mf3.py", line 120, in import_hook
    module = self._gcd_import(name)
  File "C:\Python34\lib\site-packages\py2exe\mf3.py", line 273, in _gcd_import
    raise ImportError('No module named {!r}'.format(name), name=name)
ImportError: No module named 'clr'

I also read/tried these:

https://docs.python.org/2/distutils/setupscript.html
https://pythonhosted.org/setuptools/setuptools.html
http://sourceforge.net/p/py2exe/mailman/message/6937658

leading me to move clr.pyd and Python.Runtime.dll into various locations including the location of main.py, C:\Python34\Lib\site-packages (where they were originally) and C:\Python34\Lib\site-packages\py2exe

None of these have worked and I don't know what to try next. I can see that for some reason py2exe can't find either clr.pyd or Python.Runtime.dll or both, but can't see why. Does anyone have any ideas?


Code details

My main.py script looks like this:

import clr
clr.AddReference("name.xxxx")
from name.xxxx import aaa
from clr import System

# All my functioning code, that I've verified works when run from the command line

This is what my setup.py file contains (I've left some bits commented so you can see what I've tried):

from distutils.core import setup
import py2exe, sys, os

mydata_files = []
for files in os.listdir('C:\\d\\Project\\TOOLS\\data_acquisition\\trunk\\DLL'):
    f1 = 'C:\\d\\Project\\TOOLS\\data_acquisition\\trunk\\DLL\\' + files
    if os.path.isfile(f1): # skip directories
        f2 = '.', [f1]
        mydata_files.append(f2)

setup(
  data_files=mydata_files,

  # options = {"py2exe" : {"includes" : "module1,module2,module3"}}
  options = {"py2exe": {"includes":["sip", "clr"]}},
  # options = {'py2exe': {'bundle_files': 1 , 'compressed': True,"includes":["sip"]}},
  #python setup.py py2exe
  #CLR.dll and PythonRuntime.dll 
  # options = {'py2exe': {'bundle_files': 1, "skip_archive":1 ,"includes":["sip"]}},
  windows = [{'script': "main.py"}],
  # data_files=mydata_files,
  # zipfile = None
)

If I change the line options = {"py2exe": {"includes":["sip", "clr"]}}, to options = {"py2exe": {"includes":["sip"]}}, then the .exe builds, but obviously does not function correctly.

denfromufa
  • 5,610
  • 13
  • 81
  • 138
Jesse
  • 64
  • 1
  • 7
  • In the code above, your indentation after the `for` loop is wrong. I'm *assuming* that's a typo, but if you've tried all the suggestions, it *could* be that you haven't got what you think you have in `mydata_files`. – J Richard Snape May 12 '15 at 14:51
  • It's not about the mydata_files, py2exe can't find the module clr, witch is imported in a file in my project. Any ideas? – Jesse May 19 '15 at 10:11
  • Only the ones I gave before in chat that you've now said you read and tried. My honest opinion is that Python doesn't know where `Python.Runtime.dll` is and is reporting that as an inability to import `clr`. I have never used Python.net and only responding to this as you directly asked for help. You should correct the `for` loop anyway - as it is bad to have faulty code in your question and is likely to distract anyone. I just wondered if the potential error was that the path in `mydata_files` was wrong, but if you are convinced that's not the error, that is fine - I am not an expert here. – J Richard Snape May 19 '15 at 11:36
  • Have you definitely tried putting the Python.Runtime.dll in your project's home directory like the links suggest (so it is guaranteed to be found)? Also - it will help if you paste the full traceback - then people can help you with debugging - rather than just the end message "No module named clr" – J Richard Snape May 19 '15 at 11:37
  • Actually - one more thought - it might not be able to find `clr.pyd`. A bit of googling turned up this thread - http://tech-artists.org/forum/showthread.php?666-Possible-to-use-Python-NET-or-simmilar-inside-Maya-2009-10 . For a different tool, but note the response *"The quick dirty way to get it up and running is to append the location to your sys.path in your userSetup.py or in your script. For some reason it doesn't like it if the location lives on PYTHONPATH."* Hope something in here helps you to find the problem. Let us know how it goes in these comments – J Richard Snape May 19 '15 at 11:51

1 Answers1

4

###Install description

For reference, I performed standard install of py2exe using pip install py2exe. This puts py2exe into the Lib\site-packages for your python install. Next, I installed pythonnet by downloading the .whl from Christoph Gohlke's unofficial Windows binaries page, then using pip install path\to\pythonnet-2.0.0<version_numbers>.whl. This puts clr.pyd and Python.Runtime.dll into Lib\site-packages for your python install. This question and answers have further info.

###Problem

This is a rather strange behaviour of py2exe that is hard to debug. I think it is purely a bug in that tool. In addition, the error message is not helpful.

The problem is that the module clr is specifically excluded by the tool, via its hooks.py file. It is not clear why. You can see the line that does this exclusion here.

###Solution

The workaround is to delete the word clr from the windows_excludes variable hooks.py file in your py2exe installation. Assuming everything is in its standard place - that means deleting line 23 in the file hooks.py located in C:\Python34\Lib\site-packages\py2exe. you also need to make sure that Python.Runtime.dll is somehow packaged with your .exe - I tested this by adding it to data files. Here is the example that I tested and worked - I used a very simple main.py to illustrate the import and to assure myself that the program was actually working. I left your setup.py as close as possible to your version, commenting out the lines that did not suit my system

To actually make the .exe - use the following (you may not need the path to the python.exe if python is aliased to your Python 3 install)

C:\python34\python.exe setup.py py2exe

###main.py

import clr
# I import clr, but don't use it as this is not my
# expertise.  The fact it imports without error means
# I'm pretty sure it will work

with open('out.txt','a') as f:
    for i in range(30):
        f.write(str(i))

###setup.py

from distutils.core import setup
import py2exe, sys, os

mydata_files = []

# I had to comment these out as they did not apply to my test environment
# for files in os.listdir('C:\\d\\Project\\TOOLS\\data_acquisition\\trunk\\DLL'):
# f1 = 'C:\\d\\Project\\TOOLS\\data_acquisition\\trunk\\DLL' + files
# if os.path.isfile(f1): # skip directories
    # f2 = 'dll', [f1]
    # mydata_files.append(f2)
    
# It's essential that the Python.Runtime.dll is packaged with main.exe
# This is how I've done it
mydata_files.append(('.',['C:\\Python34\\Lib\\site-packages\\Python.Runtime.dll']))

setup(
 data_files=mydata_files,

# I've left all your commented lines in - they weren't necessary for my test
# options = {"py2exe" : {"includes" : "module1,module2,module3"}}

# I haven't included sip as I don't have it installed, but I think it will work
options = {"py2exe": {"includes":["clr"]}},
# options = {'py2exe': {'bundle_files': 1 , 'compressed': True,"includes":["sip"]}},
#python setup.py py2exe
#CLR.dll and PythonRuntime.dll 
# options = {'py2exe': {'bundle_files': 1, "skip_archive":1 ,"includes":["sip"]}},
windows = [{'script': "main.py"}],
# data_files=mydata_files,
# zipfile = None
)

Edit: For anyone interested - I described how I isolated and found this bug in more detail in a chat conversation.

Community
  • 1
  • 1
J Richard Snape
  • 20,116
  • 5
  • 51
  • 79