Я уже пытался использовать py2exe (несовместимый с ipy) и PYC (устаревший). Может ли кто-нибудь указать мне в сторону хорошего компилятора?
Ironpython 2.6.py ->.exe
Ответ 1
Вы можете использовать pyc.py
, компилятор командной строки Python, который входит в состав IronPython с версии 2.6 для компиляции Python script к исполняемому файлу. Вы найдете его на %IRONPYTONINSTALLDIR%\Tools\Scripts\pyc.py
на жестком диске.
Пример
Предположим, у вас есть простой script test.py
, который просто выводит что-то на консоль. Вы можете превратить его в исполняемый файл со следующей командной строкой (если предположить, что каталог IronPython является текущим каталогом и что там находится test.py
):
ipy.exe Tools\Scripts\pyc.py /main:test.py /target:exe
Примечание. Если вы используете формы и не хотите открывать окно консоли, вы должны использовать /target:winexe
вместо /target:exe
.
В результате будут два файла: test.dll
и test.exe
. test.dll
будет содержать ваш фактический script код, а test.exe
- это просто пусковая установка для test.dll
. Вы можете распространять эти EXE и DLL на другие компьютеры, на которых не установлен IronPython, если вы включаете файлы
-
IronPython.dll
, -
Microsoft.Dynamic.dll
, -
Microsoft.Scripting.Core.dll
, -
Microsoft.Scripting.Debugging.dll
, -
Microsoft.Scripting.dll
, -
Microsoft.Scripting.ExtensionAttribute.dll
и -
IronPython.Modules.dll
(иногда требуется).
Также см. запись в блоге IronPython - как скомпилировать exe.
Ответ 2
Это давний вопрос, о котором очень мало информации в Интернете. Единственное известное решение, которое я могу найти, это http://community.sharpdevelop.net/blogs/mattward/archive/2010/03/16/CompilingPythonPackagesWithIronPython.aspx, в котором используется SharpDevelop. Однако это решение нецелесообразно, потому что любой полукомпонентный проект python будет выполнять LOT импорта модулей, а для решения SharpDevelop требуется создать проект для импорта. Я начал с него и сдался после примерно тридцати новых проектов, лучше написать автоматическое решение!
Итак, вот мое решение, и я предупрежу вас прямо сейчас, что он не будет выпущен как правильный проект по уважительной причине:
#!/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 <source py> [-outdir=<dest dir>]")
sys.exit(0)
if sys.platform=="cli":
print("ERROR: IronPython 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 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)
Это было написано против IronPython v2.7.2 RC1, используя его новую автономную двоичную функцию, и действительно, она работает. Вы получаете автономный .exe файл, который полностью автономный - ему больше ничего не нужно устанавливать. script работает путем анализа импорта для поставляемого script и отправки всей партии на pyc.py. Это хорошие новости.
Плохая новость такова:
- IronPython v2.7.2 RC1 ModuleFinder не работает, поэтому приведенный выше script должен быть запущен с использованием CPython. Затем он использует CPython ModuleFinder, но нестандартную библиотеку времени исполнения IronPython. Да, я поражен тем, что это работает...
- Выход двоичных файлов начинается примерно с 8 Мб. Простой unit test весит 16 Мб. Там много вещей, которые не обязательно должны быть там, например. он бросает поддержку Wpf и немного больше, но все же они не маленькие.
- Время загрузки намного медленнее, чем нестандартное. Подумайте о сорока секундах для автономного unit test на быстром Intel Core 2 против примерно трех секунд для не-автономного. Если скомпилировано только для x86, это сократится до десяти секунд.
- Производительность во время выполнения медленнее, чем не автономная, примерно на 40%. Если скомпилировать только для x86, производительность примерно удваивается. Вот почему я ушел в/платформу: x86 выше.
- Существует известная ошибка в кодированиях CPython и поддержке кодеков, где ModuleFinder вообще не включает поддержку кодека, если вы не указали ее вручную. Так, например, если вы используете UTF-8 с codecs.open(), вам нужно "от кодирования импортировать utf_8 как some_unique_identifier", чтобы заставить зависимость.
- Приведенное выше предполагает модифицированный pyc.py, который может принимать параметр /files, поскольку ограничение длины командной строки легко превзойдено. Вы можете изменить свой собственный pyc.py тривиально, если я не представил расширение для включения в следующий IronPython.
Итак, вы идете. Он работает, но решение по-прежнему нуждается в гораздо более зрелости. Удачи!
Ответ 3
Посмотрите Страница образцов IronPython
Примерно на полпути вниз по странице:
Компилятор командной строки Pyc - Python В этом примере разработчикам показано, как создавать исполняемые файлы .NET непосредственно из сценариев IronPython. В файле readme.htm вы загрузите файл.
API-интерфейсы IronPythons для хостинга могут использоваться для компиляции скриптов Python в библиотеки DLL, исполняемые файлы консоли или исполняемые файлы Windows. Pyc.py script, включенный в этот учебник, использует эти API-интерфейсы хостинга и может использоваться для компиляции других скриптов Python. Он предоставляет множество флагов, таких как возможность указать целевую платформу сборки .NET(например, x64).
Хотя сборки, созданные API-интерфейсами IronPython Hosting, являются настоящими сборками .NET, динамическая природа языка Python затрудняет их использование с других языков .NET. Короче говоря, это означает, что попытка импортировать типы Python в другие языки .NET, такие как С#, не рекомендуется.
Изменить: только что заметил, что вы упомянули, что PYC устарел. Что это делает? Команда IronPython, похоже, все еще поддерживает ее, поэтому я бы предположил, что она не так уж и ушла.
Ответ 4
У меня было немного проблем с попыткой реализовать это решение. Это то, что я сделал:
- Загрузите pyc из здесь. Это заняло у меня больше поисков, чем должно было быть, потому что кажется, что pyc трудно найти (и я думаю, немного устарел).
- Я извлек папку pyc из zip файла и добавил ее в папку IronPython в
C:\Program Files
- Теперь я попробовал запустить эту команду на консоли Windows, как указано в файле readme в папке pyc:
ipy.exe pyc.py other_hw.py /main:console_hw.py
Это дало мне эту ошибку:
Traceback (most recent call last):
File "pyc\pyc.py", line 35, in pyc\pyc.py
AttributeError: attribute 'CompilerSink' of 'namespace#' object is read-only
Я сделал следующее изменение в строке 35:
До: class PycSink(Hosting.CompilerSink):
После: class PycSink():
Сохранение файла оказалось проблемой из-за разрешений, поэтому я скопировал содержимое pyc.py в новое окно IDLE (чтобы создать копию), удалил существующую копию pyc.py
и сохранил копию как pyc.py
в том же месте. Это устраняет проблемы с разрешениями и позволяет изменять.
После внесения этого изменения я снова попробовал запустить эту команду:
ipy.exe pyc.py other_hw.py /main:console_hw.py
Однако на этот раз я получил следующую ошибку:
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
В этот момент я подвел итог тому, что сейчас 1 AM, и завтра у меня средний срок, поэтому я отключил изменения и отключил их.
Пожалуйста, дайте мне знать, если у вас есть решение или какие-либо улучшения на моем.
Ответ 5
Да, мне было сложно скомпилировать exe, поэтому я переключился на стандартный Python. Они должны дать хороший учебник по этому вопросу на сайте IronPython.