IronPython: EXE, скомпилированный с использованием pyc.py, не может импортировать модуль "os" - PullRequest
21 голосов
/ 01 июня 2011

У меня есть простой скрипт IronPython:

# Foo.py
import os

def main():
    print( "Hello" )

if "__main__" == __name__:
    main()

Он работает нормально и печатает Привет , если я запускаю его с IronPython как:

ipy Foo.py

Следуя инструкциям, приведенным в IronPython - как скомпилировать exe , я скомпилировал этот сценарий IronPython в EXE-файл, используя:

ipy pyc.py /main:Foo.py /target:exe

Выполнение Foo.exe выдает эту ошибку:

Unhandled Exception: IronPython.Runtime.Exceptions.ImportException: No module named os
   at Microsoft.Scripting.Runtime.LightExceptions.CheckAndThrow(Object value)
   at DLRCachedCode.__main__$1(CodeContext $globalContext, FunctionCode $functionCode)
   at IronPython.Compiler.OnDiskScriptCode.Run()
   at IronPython.Compiler.OnDiskScriptCode.Run(Scope scope)
   at IronPython.Runtime.PythonContext.InitializeModule(String fileName, ModuleContext moduleContext, ScriptCode scriptC
ode, ModuleOptions options)

Почему нельзя найти модуль "os"? Как мне это исправить, чтобы я мог получить работающий EXE?

(Обратите внимание, что это отличается от вопроса IronPython не может импортировать модуль OS , так как скрипт работает нормально, если я запускаю с ipy.exe.)

Ответы [ 2 ]

24 голосов
/ 01 июня 2011

Создание дистрибутива Ironpython, который вы можете распространять, немного сложнее, особенно если вы используете элементы стандартной библиотеки. Мое типичное решение следующее:

Я копирую все необходимые мне модули stdlib в папку (обычно все они только для полноты) и использую этот скрипт для сборки моего exe-файла. В этом примере у меня есть два файла FredMain.py и FredSOAP.py , которые скомпилированы в EXE-файл с именем Fred_Download_Tool

import sys
sys.path.append(r'C:\Program Files\IronPython 2.7\Lib')
sys.path.append(r'C:\Program Files\IronPython 2.7')
import clr

clr.AddReference('IronPython')
clr.AddReference('IronPython.Modules')
clr.AddReference('Microsoft.Scripting.Metadata')
clr.AddReference('Microsoft.Scripting')
clr.AddReference('Microsoft.Dynamic')
clr.AddReference('mscorlib')
clr.AddReference('System')
clr.AddReference('System.Data')

#
# adapted from os-path-walk-example-3.py

import os, glob
import fnmatch
import pyc

def doscopy(filename1):
    print filename1
    os.system ("copy %s .\\bin\Debug\%s" % (filename1, filename1))

class GlobDirectoryWalker:
    # a forward iterator that traverses a directory tree

    def __init__(self, directory, pattern="*"):
        self.stack = [directory]
        self.pattern = pattern
        self.files = []
        self.index = 0

    def __getitem__(self, index):
        while 1:
            try:
                file = self.files[self.index]
                self.index = self.index + 1
            except IndexError:
                # pop next directory from stack
                self.directory = self.stack.pop()
                self.files = os.listdir(self.directory)
                self.index = 0
            else:
                # got a filename
                fullname = os.path.join(self.directory, file)
                if os.path.isdir(fullname) and not os.path.islink(fullname) and fullname[-4:]<>'.svn':
                    self.stack.append(fullname)
                if fnmatch.fnmatch(file, self.pattern):
                    return fullname

#Build StdLib.DLL
gb = glob.glob(r".\Lib\*.py")
gb.append("/out:StdLib")    

#print ["/target:dll",]+gb

pyc.Main(["/target:dll"]+gb)

#Build EXE
gb=["/main:FredMain.py","FredSOAP.py","/target:exe","/out:Fred_Download_Tool"]
pyc.Main(gb)


#CopyFiles to Release Directory
doscopy("StdLib.dll")
doscopy("Fred_Download_Tool.exe")
doscopy("Fred_Download_.dll")


#Copy DLLs to Release Directory
fl = ["IronPython.dll","IronPython.Modules.dll","Microsoft.Dynamic.dll","Microsoft.Scripting.Debugging.dll","Microsoft.Scripting.dll","Microsoft.Scripting.ExtensionAttribute.dll","Microsoft.Scripting.Core.dll"]
for f in fl:

doscopy(f)

В мои сценарии я добавляю следующее, когда я готов к компиляции. Это позволяет программе использовать стандартные модули из моей DLL вместо установки Python. Это необходимо, если вы хотите раздавать людям без установленного Python. Просто убедитесь, что вы включили необходимые библиотеки DLL при создании программы установки.

#References to created DLL of python modules
clr.AddReference('StdLib')
7 голосов
/ 30 сентября 2013

Я знаю, что на это уже давно ответили, но мне все еще потребовалось МНОГО времени, чтобы заставить моего exe работать.Я указал 5 сообщений об ошибках, среди которых была эта проблема импорта.Вот что мне нужно было сделать, чтобы моя exe-программа работала:

1) включите все DLL-файлы IronPython в папку развертывания (IronPython.dll, IronPython.Modules.dll и т. Д.)

2)включите dll из стандартной библиотеки в папку deploye

3) путь, где находится ваш exe-файл, не должен содержать пробелов

(это: C: \ User1 \ MyDocuments \ My Folder \ deployFolder

должно быть изменено на это, например: C: \ User1 \ MyDocuments \ MyFolder \ deployFolder)

4) ваша ОС может заблокировать dll, используемую вашим exe-файлом, и дать вам «loadFromRemoteResource comutator»ошибка блаблабла ".Чтобы это исправить, вам нужно щелкнуть правой кнопкой мыши на dll и нажать «разблокировать» в последней строке окна.

5) наконец, не забудьте включить файл dll, заданный pyc, в ваш exe-файл (то же имя, только разница в расширении)

Вот статья, которую я написал с более подробной информацией, если вам это нужно: http://thesesergio.wordpress.com/2013/09/11/how-to-generate-and-use-a-exe-that-uses-net-dlls-with-ironpython-pyc-py/

...