Ironpython 2.6 .py -> .exe

Ho già provato a usare py2exe (non compatibile con ipy) e PYC (non aggiornato). Qualcuno può indicarmi la direzione di un buon compilatore?

È ansible utilizzare pyc.py , il compilatore della riga di comando Python , incluso in IronPython dalla versione 2.6 per compilare uno script Python su un eseguibile. Lo trovi in %IRONPYTONINSTALLDIR%\Tools\Scripts\pyc.py sul tuo disco rigido.

Esempio

Supponiamo che tu abbia un semplice script test.py che stampa solo qualcosa da console. Puoi trasformarlo in un eseguibile con la seguente riga di comando (assumendo che la directory di IronPython sia la directory corrente e che test.py sia anche lì):

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

Nota: se si utilizzano i moduli e non si desidera aprire una finestra della console, si desidera utilizzare /target:winexe anziché /target:exe .

Il risultato saranno due file, test.dll e test.exe . test.dll conterrà il tuo codice di script effettivo, mentre test.exe è solo un lanciatore per test.dll . È ansible distribuire questo EXE e DLL ad altri computer su cui non è installato IronPython se si includono i file

  • IronPython.dll ,
  • Microsoft.Dynamic.dll ,
  • Microsoft.Scripting.Core.dll ,
  • Microsoft.Scripting.Debugging.dll ,
  • Microsoft.Scripting.dll ,
  • Microsoft.Scripting.ExtensionAttribute.dll e
  • IronPython.Modules.dll (a volte necessario).

Vedi anche il blog entry IronPython – come compilare exe .

Questa è una domanda di vecchia data su cui ci sono pochissime informazioni su internet. L’unica soluzione nota che riesco a trovare è http://community.sharpdevelop.net/blogs/mattward/archive/2010/03/16/CompilingPythonPackagesWithIronPython.aspx che utilizza SharpDevelop. Tuttavia, questa soluzione è poco pratica perché qualsiasi progetto python semi-complesso farà un sacco di importazioni di moduli e la soluzione SharpDevelop richiede la creazione di un progetto per importazione . Ho iniziato e ho rinunciato a circa trenta nuovi progetti, meglio scrivere una soluzione automatizzata!

Quindi, ecco la mia soluzione, e ti avverto in questo momento che non viene rilasciato come progetto adatto per una buona ragione:

 #!/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) 

Questo è stato scritto contro IronPython v2.7.2 RC1 usando la sua nuova funzionalità binaria autonoma, e in effetti funziona. Ottieni un file .exe autonomo che è totalmente autonomo – non ha bisogno di nient’altro installato. Lo script funziona analizzando le importazioni per lo script fornito e inviando l’intero lotto a pyc.py. Questa è la buona notizia.

Le cattive notizie sono le seguenti:

  1. IronPython v2.7.2 ModuleFinder di RC1 non sembra funzionare, quindi lo script sopra deve essere eseguito usando CPython. Quindi usa ModuleFinder di CPython ma contro la libreria di runtime personalizzata di IronPython. Sì, sono stupito che funzioni pure …
  2. L’output dei binari inizia a circa 8 Mb. Un semplice test di unità ha pesato a 16 Mb. Ci sono molte cose che non hanno bisogno di essere lì, ad esempio lo getta Wpf e un po ‘di più, ma ancora non sono piccole.
  3. I tempi di caricamento sono molto più lenti di quelli non standalone. Pensa a quaranta secondi per un test di unità stand-alone su un Intel Core 2 veloce rispetto a circa tre secondi per non standalone. Se compilato solo per x86, scende a dieci secondi.
  4. Le prestazioni in fase di esecuzione sono più lente rispetto a quelle non standalone di circa il 40%. Se compilato solo per x86, le prestazioni sono all’incirca doppie. Questo è il motivo per cui ho lasciato in / platform: x86 sopra.
  5. C’è un bug ben noto nelle codifiche di CPython e nel supporto dei codec in cui ModuleFinder non include alcun supporto codec, a meno che non lo specifichi manualmente. Quindi, ad esempio, se si utilizza UTF-8 con codecs.open (), allora è necessario un “da encodings import utf_8 as some_unique_identifier” per forzare la dipendenza.
  6. Quanto sopra presuppone un pyc.py modificato che può assumere un parametro / files poiché il limite di lunghezza della riga di comando viene facilmente superato. È ansible modificare il proprio pyc.py banalmente, se non ho presentato il miglioramento per l’inclusione nel prossimo IronPython.

Quindi eccoti. Funziona, ma la soluzione ha ancora bisogno di molta più maturazione. Buona fortuna!

Controlla la pagina degli esempi IronPython

Circa a metà della pagina:

Pyc – Python Command-Line Compiler Questo esempio mostra agli sviluppatori come creare eseguibili .NET direttamente dagli script IronPython. Il file readme.htm ti consentirà di iniziare.

Le API Hosting di IronPython possono essere utilizzate per compilare script Python in DLL, eseguibili di console o eseguibili di Windows. Lo script pyc.py incluso in questo tutorial sfrutta queste API di hosting e può essere utilizzato per compilare altri script Python. Fornisce una varietà di flag come la possibilità di specificare la piattaforma di destinazione dell’assembly .NET (ad esempio, x64).

Mentre gli assembly prodotti dalle API Hosting di IronPython sono veri assembly .NET, la natura dynamic del linguaggio Python rende difficile l’uso di questi da altri linguaggi .NET. In breve, questo significa che il tentativo di importare i tipi Python in altri linguaggi .NET come C # non è raccomandato.

Modifica: ho appena notato che hai menzionato PYC non aggiornato. Cosa lo rende così? L’equipaggio di IronPython sembra ancora promuoverlo, quindi immagino che non sia poi così lontano.

Ho avuto un po ‘di problemi nel tentativo di implementare questa soluzione. Questo è quello che ho fatto:

  1. Scarica pyc da qui . Questo mi ha portato più a cercare di quanto avrebbe dovuto, perché sembra che il pyc sia difficile da trovare (e penso, un po ‘antiquato)
  2. Ho estratto la cartella pyc dal file zip e l’ho aggiunta alla mia cartella IronPython in C:\Program Files
  3. Ora ho provato a eseguire questo comando sulla console di Windows, come indicato dal readme nel download di ipy.exe pyc.py other_hw.py /main:console_hw.py : ipy.exe pyc.py other_hw.py /main:console_hw.py

Mi ha dato questo errore:

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

Ho apportato la seguente modifica alla riga 35:

Prima: class PycSink(Hosting.CompilerSink):

Dopo: class PycSink():

Il salvataggio del file si è rivelato un problema dovuto alle autorizzazioni, quindi ho copiato il contenuto di pyc.py in una nuova finestra IDLE (per creare una copia), cancellato la copia esistente di pyc.py e salvato la copia come pyc.py in la stessa posizione Questo si occupa dei problemi relativi alle autorizzazioni e consente modifiche.

Dopo aver apportato questa modifica, ho provato a eseguire nuovamente questo comando:

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

Tuttavia, questa volta, ho ricevuto il seguente errore:

 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 

A questo punto, ho preso atto del fatto che ora sono le 1:00 e domani ho un midterm, quindi ho annullato le modifiche e l’ho chiuso.

Per favore fatemi sapere se avete una soluzione, o eventuali progressi sul mio.

Sì, ho trovato troppo difficile compilare un exe quindi sono tornato a utilizzare Python standard. Dovrebbero fornire un buon tutorial sul sito IronPython