Подтвердить что ты не робот

IronPython: EXE, скомпилированный с использованием pyc.py, не может импортировать модуль "os"

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

# Foo.py
import os

def main():
    print( "Hello" )

if "__main__" == __name__:
    main()

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

ipy Foo.py

Следуя инструкциям, приведенным в IronPython - как скомпилировать exe, я скомпилировал этот IronPython script в 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, поскольку script отлично работает, если я запускаю с ipy.exe.)

4b9b3361

Ответ 1

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

Я копирую все модули stdlib, которые мне нужны, в папку (обычно все они просто для полноты), и используйте этот script для сборки моего 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 Install. Это необходимо, если вы хотите распространять людей без установленного Python. Просто убедитесь, что вы включили необходимую DLL при создании установщика.

#References to created DLL of python modules
clr.AddReference('StdLib')

Ответ 2

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

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

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

3) путь, в котором находится ваш exe, не должен содержать пробела

(это: C:\User1\MyDocuments\Моя папка \deployFolder

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

4) ваши os могут заблокировать dll, используемую вашим exe файлом, и дать вам "load.fromRemoteResource comutator error blablabla". Чтобы исправить это, вам нужно щелкнуть правой кнопкой мыши по 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/