Ironpython 2.6 .py -> .exe

Ya intenté usar py2exe (no compatible con ipy) y PYC (desactualizado). ¿Puede alguien señalarme un buen comstackdor?

Puede usar pyc.py , el comstackdor de línea de comandos de Python , que se incluye en IronPython desde la versión 2.6 para comstackr un script de Python en un archivo ejecutable. Lo encontrará en %IRONPYTONINSTALLDIR%\Tools\Scripts\pyc.py en su disco duro.

Ejemplo

Supongamos que tiene un script simple test.py que solo imprime algo para la consola. Puede convertir esto en un archivo ejecutable con la siguiente línea de comando (suponiendo que el directorio de IronPython es el directorio actual y que test.py está allí también):

 ipy.exe Tools\Scripts\pyc.py /main:test.py /target:exe 

Nota: Si está utilizando formularios y no quiere que se abra una ventana de la consola, quiere usar /target:winexe lugar de /target:exe .

El resultado será dos archivos, test.dll y test.exe . test.dll contendrá el código de script real, mientras que test.exe es solo un test.dll para test.dll . Puede distribuir este EXE y DLL a otras computadoras que no tengan instalado IronPython si incluye los archivos

  • IronPython.dll ,
  • Microsoft.Dynamic.dll ,
  • Microsoft.Scripting.Core.dll ,
  • Microsoft.Scripting.Debugging.dll ,
  • Microsoft.Scripting.dll ,
  • Microsoft.Scripting.ExtensionAttribute.dll y
  • IronPython.Modules.dll (a veces es necesario).

También vea la entrada del blog IronPython – cómo comstackr exe .

Esta es una pregunta de larga data sobre la cual hay muy poca información en internet. La única solución conocida que puedo encontrar está en http://community.sharpdevelop.net/blogs/mattward/archive/2010/03/16/CompilingPythonPackagesWithIronPython.aspx que usa SharpDevelop. Sin embargo, esta solución no es práctica porque cualquier proyecto python semi-complejo hará MUCHAS importaciones de módulos, y la solución SharpDevelop requiere que usted cree un proyecto por importación . Empecé y me rendí después de una treintena de nuevos proyectos, ¡mejor escribir una solución automática!

Así que aquí está mi solución, y te advertiré en este momento que no se está lanzando como un proyecto adecuado por una buena razón:

 #!/usr/bin/env python # CompileToStandalone, a Python to .NET ILR compiler which produces standalone binaries # (C) 2012 Niall Douglas http://www.nedproductions.biz/ # Created: March 2012 import modulefinder, sys, os, subprocess, _winreg if len(sys.argv)<2: print("Usage: CompileEverythingToILR.py  [-outdir=]") sys.exit(0) if sys.platform=="cli": print("ERROR: IronPython's ModuleFinder currently doesn't work, so run me under CPython please") sys.exit(1) sourcepath=sys.argv[1] destpath=sys.argv[2][8:] if len(sys.argv)==3 else os.path.dirname(sys.argv[0]) ironpythonpath=None try: try: keyh=_winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\IronPython\\2.7\\InstallPath") ironpythonpath=_winreg.QueryValue(keyh, None) except Exception as e: try: keyh=_winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\Wow6432Node\\IronPython\\2.7\\InstallPath") ironpythonpath=_winreg.QueryValue(keyh, "") except Exception as e: pass finally: if ironpythonpath is not None: _winreg.CloseKey(keyh) print("IronPython found at "+ironpythonpath) else: raise Exception("Cannot find IronPython in the registry") # What we do now is to load the python source but against the customised IronPython runtime # library which has been hacked to work with IronPython. This spits out the right set of # modules mostly, but we include the main python's site-packages in order to resolve any # third party packages print("Scanning '"+sourcepath+"' for dependencies and outputting into '"+destpath+"' ...") searchpaths=[".", ironpythonpath+os.sep+"Lib"] searchpaths+=[x for x in sys.path if 'site-packages' in x] finder=modulefinder.ModuleFinder(searchpaths) finder.run_script(sourcepath) print(finder.report()) modules=[] badmodules=finder.badmodules.keys() for name, mod in finder.modules.iteritems(): path=mod.__file__ # Ignore internal modules if path is None: continue # Ignore DLL internal modules #if '\\DLLs\\' in path: continue # Watch out for C modules if os.path.splitext(path)[1]=='.pyd': print("WARNING: I don't support handling C modules at '"+path+"'") badmodules.append(name) continue modules.append((name, os.path.abspath(path))) modules.sort() print("Modules not imported due to not found, error or being a C module:") print("\n".join(badmodules)) raw_input("\nPress Return if you are happy with these missing modules ...") with open(destpath+os.sep+"files.txt", "w") as oh: oh.writelines([x[1]+'\n' for x in modules]) cmd='ipy64 '+destpath+os.sep+'pyc.py /main:"'+os.path.abspath(sourcepath)+'" /out:'+os.path.splitext(os.path.basename(sourcepath))[0]+' /target:exe /standalone /platform:x86 /files:'+destpath+os.sep+'files.txt' print(cmd) cwd=os.getcwd() try: os.chdir(destpath) retcode=subprocess.call(cmd, shell=True) finally: os.chdir(cwd) sys.exit(retcode) 

Esto fue escrito contra IronPython v2.7.2 RC1 usando su nueva característica binaria independiente, y de hecho funciona. Obtienes un archivo .exe independiente que es totalmente autónomo, no necesita nada más. El script funciona analizando las importaciones para el script suministrado y enviando todo el lote a pyc.py. Esa es la buena noticia.

Las malas noticias son las siguientes:

  1. El ModuleFinder de IronPython v2.7.2 RC1 no parece funcionar, por lo que el script anterior debe ejecutarse utilizando CPython. Luego usa ModuleFinder de CPython pero en contra de la biblioteca de tiempo de ejecución personalizada de IronPython. Sí, estoy sorprendido de que también funcione …
  2. La salida de los binarios comienza en aproximadamente 8Mb. Una simple prueba unitaria pesó 16Mb. Hay muchas cosas que no necesitan estar allí, por ejemplo, le da soporte a Wpf y un poco más, pero aún así no son pequeñas.
  3. Los tiempos de carga son mucho más lentos que los no independientes. Piensa en unos cuarenta segundos para una prueba de unidad independiente en un Intel Core 2 rápido en lugar de tres segundos para los no independientes. Si se comstack solo para x86, eso se reduce a diez segundos.
  4. El rendimiento del tiempo de ejecución es más lento que el no autónomo en aproximadamente un 40%. Si se comstack solo para x86, el rendimiento se duplicará aproximadamente. Es por eso que dejé en / plataforma: x86 arriba.
  5. Existe un error muy conocido en las codificaciones y códecs de CPython, donde ModuleFinder no incluye ningún soporte de códec a menos que usted lo especifique manualmente. Entonces, por ejemplo, si está usando UTF-8 con codecs.open () entonces NECESITA un “from encodings import utf_8 como some_unique_identifier” para forzar la dependencia.
  6. Lo anterior supone un pyc.py modificado que puede tomar un parámetro / files ya que el límite de longitud de línea de comando se excede fácilmente. Puedes modificar tu propio pyc.py trivialmente, si no, he enviado la mejora para incluirla en el próximo IronPython.

Ahí vas. Funciona, pero la solución aún necesita mucha más maduración. ¡La mejor de las suertes!

Consulte la página de ejemplos de IronPython

A mitad de camino de la página:

Pyc – Comstackdor de la línea de comandos de Python Este ejemplo muestra a los desarrolladores cómo crear ejecutables .NET directamente desde los scripts de IronPython. El archivo readme.htm en la descarga lo ayudará a comenzar.

Las API de Hosting de IronPython se pueden usar para comstackr scripts de Python en DLL, ejecutables de consola o ejecutables de Windows. El script pyc.py incluido en este tutorial aprovecha estas API de alojamiento y puede usarse para comstackr otros scripts de Python. Proporciona una variedad de indicadores, como la capacidad de especificar la plataforma de destino del ensamblado .NET (por ejemplo, x64).

Si bien los ensamblados producidos por las API de Hospedaje de IronPython son ensamblajes de .NET verdaderos, la naturaleza dinámica del lenguaje de Python hace que sea difícil usarlos de otros lenguajes .NET. En resumen, esto significa que no se recomienda intentar importar tipos de Python a otros lenguajes .NET como C #.

Editar: Acabo de notar que usted mencionó que PYC estaba desactualizado. ¿Qué lo hace así? El equipo de IronPython parece seguir promocionándolo, así que me imagino que no está tan lejos.

Tuve algunos problemas para tratar de implementar esta solución. Esto es lo que hice:

  1. Descargar pyc desde aquí . Esto me llevó a buscar más de lo que debería porque parece que pyc es difícil de encontrar (y creo que está un poco desactualizado)
  2. Extraje la carpeta pyc del archivo zip y la agregué a mi carpeta IronPython en C:\Program Files
  3. Ahora traté de ejecutar este comando en la consola de Windows, como lo indica el archivo léame en la descarga de ipy.exe pyc.py other_hw.py /main:console_hw.py : ipy.exe pyc.py other_hw.py /main:console_hw.py

Me dio este error:

 Traceback (most recent call last): File "pyc\pyc.py", line 35, in pyc\pyc.py AttributeError: attribute 'CompilerSink' of 'namespace#' object is read-only 

Hice el siguiente cambio a la línea 35:

Antes: class PycSink(Hosting.CompilerSink):

Después: class PycSink():

Guardar el archivo resultó ser un problema debido a los permisos, así que copié el contenido de pyc.py en una nueva ventana IDLE (para crear una copia), pyc.py copia existente de pyc.py y pyc.py la copia como pyc.py en el mismo lugar Esto se ocupa de los problemas de permisos y permite cambios.

Después de hacer este cambio, intenté ejecutar este comando nuevamente:

ipy.exe pyc.py other_hw.py /main:console_hw.py

Sin embargo, esta vez, recibí el siguiente error:

 Traceback (most recent call last): File "pyc\pyc.py", line 170, in pyc\pyc.py File "pyc\pyc.py", line 56, in Main AttributeError: attribute 'ResourceFile' of 'namespace#' object is read-only 

En este punto, hice un recuento del hecho de que ahora es la 1 AM y tengo un término medio mañana, así que deshice los cambios y lo cerré.

Por favor, avíseme si tiene una solución o algún avance en la mía.

Sí, me ha resultado muy difícil comstackr un exe, así que volví a usar Python estándar. Deberían dar un buen tutorial en el sitio de IronPython