example - IronPython: el EXE compilado usando pyc.py no puede importar el módulo "os"
ironpython virus (2)
Tengo un simple script de IronPython:
# Foo.py
import os
def main():
print( "Hello" )
if "__main__" == __name__:
main()
Funciona bien e imprime Hola si lo ejecuto con IronPython como:
ipy Foo.py
Siguiendo las instrucciones dadas en IronPython: cómo compilar exe , compilé este script de IronPython en un EXE usando:
ipy pyc.py /main:Foo.py /target:exe
Ejecutar Foo.exe da este error:
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)
¿Por qué no se puede encontrar el módulo "os"? ¿Cómo soluciono esto, para que pueda obtener un EXE que funcione?
(Tenga en cuenta que esto es diferente de la pregunta de que IronPython no puede importar el sistema operativo desde que el script funciona bien si ejecuto con ipy.exe
).
Crear un EXE de Ironpython que pueda distribuir es un poco complicado, especialmente si está utilizando elementos de la biblioteca estándar. Mi solución típica es la siguiente:
Copio todos los módulos stdlib que necesito en una carpeta (generalmente todos ellos solo para completar) y uso este script para compilar mi exe. En este ejemplo tengo dos archivos FredMain.py y FredSOAP.py que se compilan en un EXE llamado 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)
En mis scripts agrego lo siguiente cuando estoy listo para compilar. Esto permite que el programa use los módulos estándar de mi DLL en lugar de la instalación de Python. Esto es necesario si desea distribuir a personas sin Python instalado. Solo asegúrese de incluir los archivos DLL necesarios cuando cree su instalador.
#References to created DLL of python modules
clr.AddReference(''StdLib'')
Sé que esto ha sido respondido por mucho tiempo pero aún así me tomó MUCHO tiempo para que mi ex trabajo funcione. Señalé 5 mensajes de error entre los cuales había este problema de importación. Esto es lo que tuve que hacer para que mi ex trabajo funcione:
1) incluir todos los archivos DLL de IronPython en la carpeta de implementación (IronPython.dll, IronPython.Modules.dll, etc.)
2) incluir archivos DLL de la biblioteca estándar en la carpeta de despliegue
3) el camino donde se encuentra su exe no debe tener espacio
(esto: C: / User1 / MyDocuments / My Folder / deployFolder
debería cambiarse a eso, por ejemplo: C: / User1 / MyDocuments / MyFolder / deployFolder)
4) su sistema operativo puede bloquear una dll utilizada por su archivo exe y le dará un "loadFromRemoteResource comutator error blablabla". Para solucionarlo, debe hacer clic con el botón derecho en la dll y presionar "desbloquear" en la última línea de la ventana.
5) finalmente, no olvides incluir el archivo dll proporcionado por pyc con tu archivo exe (mismo nombre, solo una diferencia en la extensión)
Aquí hay un artículo que escribí con más detalles si lo necesita: http://thesesergio.wordpress.com/2013/09/11/how-to-generate-and-use-a-exe-that-uses-net-dlls-with-ironpython-pyc-py/