Статья познакомит программистов C/C++ с Python/C API, библиотекой C, помогающей встраивать модули Python в приложения C/C++. Библиотека API предоставляет множество подпрограмм C для инициализации интерпретатора Python, вызова модулей Python и завершения встраивания. Библиотека скомпилирована с Python и распространяется со всеми последними выпусками Python.
Введение
Статья «Встраивание Python в многопоточные приложения C/C++» (Linux Journal) вдохновила на более глубокое освещение темы встраивания Python. Эта статья написана с двумя целями:
1. Она написана для программистов, более опытных в C/C++, чем в Python. Руководство применяет практический подход и пропускает все теоретические рассуждения.
2. Постараться сохранить межплатформенную совместимость Python при написании кода встраивания.
Имеются модули, написанные другими на Python, которые надо использовать. Вы разбираетесь в C/C++, но мало знакомы с Python. Нет инструмента для преобразования их в код C, как преобразование из FORTRAN. Однако некоторые инструменты генерируют исполнимый модуль из модуля Python. Но они не решают проблему.
Установка Python под Windows. Устраняем ошибки.
Преобразование кода в исполнимые модули обычно все усложняет, так как приходится выяснять, как приложение C/C++ взаимодействует с исполнимым «черным ящиком».
Первая часть серии статей рассматривает основы встраивания Python. Вторая часть переходит к более продвинутым темам. Это руководство не обучает языку Python систематически, но кратко описывается, как работает код Python, когда он появляется. Акцент будет на то, как внедрить модули Python в приложения C/C++. Смотрите статью: «Встраивание Python в C/C++: вторая часть».
Чтобы использовать исходный код, надо установить последний выпуск Python, Visual C++ (или компилятор GCC на Linux). Тесты проводились в следующей среде: Python 2.4 (Windows и Linux), Visual C++ 6.0 (Windows) или GCC 3.2 (RedHat 8.0 Linux). В случае Visual C++ выберите конфигурацию выпуска для компиляции. Конфигурация отладки требует библиотеку отладки Python «python24_d.lib», не поставляемую с нормальными сборками.
Справка
Python – мощный интерпретируемый язык, как Java, Perl и PHP. Он обладает множеством прекрасных свойств, ожидаемых программистами, в том числе «простотой» и «переносимостью». Помимо доступных инструментов и библиотек, язык Python хорошо подходит для моделирования. Он бесплатный, и инструменты и библиотеки, написанные для программистов Python, тоже бесплатные. Более подробно о языке читайте на официальном сайте.
Азы встраивания: функции, классы и методы
Сначала рассматривается пример программы на C, вызывающей функцию в модуле Python. Ниже приведен исходный файл «call_function.c»:
// call_function.c – пример вызова
// функций python из кода C
//
#include
int main(int argc, char *argv[])
PyObject *pName, *pModule, *pDict, *pFunc, *pValue;
мой первый код на python (простой)
if (argc < 3)
printf(«Usage: exe_name python_source function_namen»);
return 1;
>
// Инициализировать интерпретатор Python
Py_Initialize();
// Построить объект имени
pName = PyString_FromString(argv[1]);
// Загрузить объект модуля
pModule = PyImport_Import(pName);
// pDict – заимствованная ссылка
pDict = PyModule_GetDict(pModule);
// pFunc – тоже заимствованная ссылка
pFunc = PyDict_GetItemString(pDict, argv[2]);
if (PyCallable_Check(pFunc))
PyObject_CallObject(pFunc, NULL);
> else
PyErr_Print();
>
// Вернуть ресурсы системе
Py_DECREF(pModule);
Py_DECREF(pName);
// Завершить интерпретатор Python
Py_Finalize();
return 0;
>
Исходный файл Python «py_function.py» выглядит так:
»’py_function.py – исходник Python, служащий для»’
»’демонстрации применения встраивания python»’
def multiply():
c = 12345*6789
print ‘The result of 12345 x 6789 :’, c
return c
Проверки на действительность объектов пропускаются для краткости. В Windows компилируется исходник C и получается исполнимый модуль по имени «call_function.exe». Для его запуска введите в командную строку «call_function py_function multiply». Второй аргумент является именем файла Python (без расширения), который при загрузке становится именем модуля.
Третий аргумент является именем функции Python, вызываемой в модуле. Исходник Python не участвует в компиляции или компоновке; он только загружается и интерпретируется во время выполнения. Вывод из выполнения следующий:
The result of 12345 x 6789 : 83810205
Сам код C не требует разъяснений, не считая того, что:
• Все в Python является объектом. pDict и pFunc являются заимствованными ссылками, поэтому не нужно Py_DECREF() их.
• Все вызовы Py_XXX и PyXXX_XXX являются вызовами Python/C API.
• Код компилируется и выполняется на всех платформах, поддерживаемых Python.
Теперь надо передать аргументы функции Python. Добавляется блок для обработки аргументов для вызова:
if (PyCallable_Check(pFunc))
// Подготовить список аргументов для вызова
if( argc > 3 )
pArgs = PyTuple_New(argc — 3);
for (i = 0; i < argc — 3; i++)
pValue = PyInt_FromLong(atoi(argv[i + 3]));
if (!pValue)
PyErr_Print();
return 1;
>
PyTuple_SetItem(pArgs, i, pValue);
>
pValue = PyObject_CallObject(pFunc, pArgs);
if (pArgs != NULL)
Py_DECREF(pArgs);
>
> else
pValue = PyObject_CallObject(pFunc, NULL);
>
if (pValue != NULL)
printf(«Return of call : %dn», PyInt_AsLong(pValue));
Py_DECREF(pValue);
>
else
PyErr_Print();
>
// некоторый код пропущен.
>
Новый исходник C добавляет блок «Подготовить список аргументов для вызова» и проверку возвращаемого значения. Он создает кортеж (спископодобный тип) для хранения всех параметров для вызова. Выполнение команды «call_function py_source multiply1 6 7» дает вывод:
The result of 6 x 7 : 42
Return of call : 42
Легко писать классы на Python. Также легко использовать класс Python в коде C. Надо лишь создать экземпляр объекта и вызвать его методы, так же как вызываются нормальные функции. Пример ниже:
// call_class.c – пример встраивания python
// (вызов классов python из кода C)
//
#include
int main(int argc, char *argv[])
PyObject *pName, *pModule, *pDict,
*pClass, *pInstance, *pValue;
int i, arg[2];
if (argc < 4)
printf(
«Usage: exe_name python_fileclass_name function_namen»);
return 1;
>
// некоторый код пропущен.
// построить имя вызываемого класса
pClass = PyDict_GetItemString(pDict, argv[2]);
// создать экземпляр класса
if (PyCallable_Check(pClass))
pInstance = PyObject_CallObject(pClass, NULL);
>
// построить список параметров
if( argc > 4 )
for (i = 0; i < argc — 4; i++)
arg[i] = atoi(argv[i + 4]);
>
// вызвать метод класса с двумя параметрами
pValue = PyObject_CallMethod(pInstance,
argv[3], «(ii)», arg[0], arg[1]);
> else
// вызвать метод класса без параметров
pValue = PyObject_CallMethod(pInstance, argv[3], NULL);
>
if (pValue != NULL)
printf(«Return of call : %dn», PyInt_AsLong(pValue));
Py_DECREF(pValue);
>
else
PyErr_Print();
>
// некоторый код пропущен.
>
Третий параметр для PyObject_CallMethod(), «(ii)» является форматирующей строкой, указывающей, что следующие аргументы – два целых числа. PyObject_CallMethod() принимает типы переменных C как свои аргументы, а не как объекты Python. Этим он отличается от других вызовов, встречавшихся до сих пор. Исходник Python «py_class.py» выглядит так:
»’py_class.py — исходник Python, служащий для»’
»’демонстрации применения встраивания python»’
class Multiply:
def __init__(self):
self.a = 6
self.b = 5
def multiply(self):
c = self.a*self.b
print ‘The result of’, self.a, ‘x’, self.b, ‘:’, c
return c
def multiply2(self, a, b):
c = a*b
print ‘The result of’, a, ‘x’, b, ‘:’, c
return c
Для запуска приложения добавляется имя класса между именами модуля и функции, являющейся «Multiply» в данном случае. Командная строка становится «call_class py_class Multiply multiply» или «call_class py_class Multiply multiply2 9 9».
Источник: www.cyberguru.ru
Python-сообщество
- Начало
- » Python для новичков
- » Запуск .py двойным щелчком в Windows7
#1 Май 25, 2013 02:32:18
Запуск .py двойным щелчком в Windows7
Здравствуйте.
Всего несколько часов изучаю Python и вообще программирование, поэтому не судите строго за ламерский вопрос..
Итак, я хочу при двойном щелчке на файл .py получать окошко ‘hello world!’.
На данный момент сделал GUI в Qt 4.8.4 на Python 3.3. Это окошко я могу запускать из командной строки и все работает как надо, но хотелось бы запускать простым двойным щелчком.
Я так понимаю, что когда я щелкаю по .py-файлу вылетает cmd, сама программа мгновенно исполняется и все закрывается. Так вот есть-ли способ остановить это мгновенное выполнение? Я знаю, что обычно ставится строка input(), но я ее тыкаю в разные места исходного кода и никакого эффекта не наблюдается. К тому же, такой вариант не слишком изящный. Я хочу чтоб, программа и cmd закрывались по нажатию крестика на окошке.
#2 Май 25, 2013 06:06:31
Запуск .py двойным щелчком в Windows7
Целых ПАРУ часов изучаете Python и уже за GUI взялись? ну гений, что тут сказать.
Python программы принято запускать из cmd, если хотите в windows по двойному щелчку, то делайте. ЧТо касается GUI — называйте исполняемый файл с расширением *.pyw и привязывайте его в Windows на исполнение через pythonw.exe.
Консольных програм это не касатеся, а то что вы хотите — ну это милион милионов раз обсуждалось на каждом первом форуме по программированию на python. Дружите чаще с Гуглом, он действительно много знает.
_________________________________________________________________________________
полезный блог о python john16blog.blogspot.com
#3 Май 25, 2013 07:37:58
Запуск .py двойным щелчком в Windows7
У вас похоже пробел не в питоне а в знаниях об операционной системе.
vshnukrshna
но хотелось бы запускать простым двойным щелчком.
Я так понимаю консоль у вас открывается, значит и программа запускается. Этот вопрос снят. А так windows решает что делать с файлом по его расширению. По умолчанию установщик питона делает ассоциацию на python.exe файлов *.py *.pyw. Если что-то сломалось по правой кнопке отредактируйте свойства — раздел тип файла — и выберете правильно приложение.
vshnukrshna
программа и cmd закрывались по нажатию крестика на окошке
Научите как вы сделали что это не так.
Я заморочился и написал мегапрограмму:
print(«hello») input()
Консольное окно прекрасно закрывается при:
1 нажатии enter
2 ctrl+C
3 нажатии на крестик
Кстати нажатие на крестик не рекомендую, долго и все равно что выгнать программу из туалета не дав ей надеть штаны.
т.е. Приводите максимально упрощенный пример программы которая вызывает у вас проблему.
Отредактировано doza_and (Май 25, 2013 07:38:38)
#4 Май 29, 2013 02:31:37
Запуск .py двойным щелчком в Windows7
Спасибо.
Как пример, привожу код:
from PyQt4 import QtGui, QtCore class Window(QtGui.QWidget): def __init__(self): QtGui.QWidget.__init__(self) self.button = QtGui.QPushButton(‘Test’, self) self.button.clicked.connect(self.handleButton) layout = QtGui.QVBoxLayout(self) layout.addWidget(self.button) def handleButton(self): print (‘Hello World’) if __name__ == ‘__main__’: import sys app = QtGui.QApplication(sys.argv) window = Window() window.show() sys.exit(app.exec_())
Через CMD все замечательно, но если переименовать в .pyw и затем щелкнуть два раза, то ничего даже не запускается…
И еще проблема: интерфейс PyQt как-то уж слишком глючно работает..навожу курсор на кнопки в меню (Файл, Правка, Вид…Справка…и.т.д.) и они выделяются но не нажимаются.А иногда нажимаются. Вообщем какая-то чертовщина.
Отредактировано vshnukrshna (Май 29, 2013 03:22:21)
#5 Май 29, 2013 10:45:40
Запуск .py двойным щелчком в Windows7
vshnukrshna
Спасибо.Как пример, привожу код:
Очень странно, ваш код даже без изменений в файле с расширением *.pyw запустился без проблем.
Заметил, что PyQT для пайтона 3.3 действительно сильно глюкав, советую 2.7 и горя не будет
Нет сегодняшних ошибок, есть вчерашние недоработки.
Отредактировано ZeUsM (Май 29, 2013 10:46:26)
#6 Май 29, 2013 22:31:11
Запуск .py двойным щелчком в Windows7
vshnukrshna
то ничего даже не запускается…
Ну дальше берите мою мегапрограмму и посмотрите как она будет себя вести.
переименовав в *.pyw получите что она “не выполняется”.
модифицируем код и проверяем еще раз:
print(«hello») open(«aa.dat»,»w»).write(«hello») input()
У меня получается файл aa.dat.
#7 Май 30, 2013 01:50:08
Запуск .py двойным щелчком в Windows7
Спасибо за ответы!
Так, вообщем откатился на python 2.7. Теперь .pyw работает так как надо и тему, в принципе, можно было бы закрывать, но… мне этого мало . Теперь я хочу преобразовать этот .pyw в .exe. Я использовал cx_Freeze, и exe создается и, вроде, даже без ошибок, но не работает. Щелкаю по нему — вылетает CMD и тут же закрывается. И все.
Далее, пробую py2exe, но получаю сообщение, что нет какого-то MSVCP90.dll. Ребята, можете доступно объяснить что надо делать и какой компилятор лучше использовать?
#8 Май 30, 2013 12:09:16
Запуск .py двойным щелчком в Windows7
vshnukrshna
Спасибо за ответы!Так, вообщем откатился на python 2.7. Теперь .pyw работает так как надо и тему, в принципе, можно было бы закрывать, но… мне этого мало . Теперь я хочу преобразовать этот .pyw в .exe. Я использовал cx_Freeze, и exe создается и, вроде, даже без ошибок, но не работает. Щелкаю по нему — вылетает CMD и тут же закрывается. И все.
Далее, пробую py2exe, но получаю сообщение, что нет какого-то MSVCP90.dll. Ребята, можете доступно объяснить что надо делать и какой компилятор лучше использовать?
Для 2.7 я использовал pyinstaller он умеет работать с Qt, делает 1 файл *.exe (опция -F) -w соберет без консоли, можно задавать иконки, использовать UPX и много ещё чего. Использование очень простое (как мне показалось).
Нет сегодняшних ошибок, есть вчерашние недоработки.
#9 Май 30, 2013 19:34:48
Запуск .py двойным щелчком в Windows7
ZeUsM
Для 2.7 я использовал pyinstaller он умеет работать с Qt, делает 1 файл *.exe (опция -F) -w соберет без консоли, можно задавать иконки, использовать UPX и много ещё чего. Использование очень простое (как мне показалось).
Спасибо. Попробовал Pyinstaller2.0.
Простой код, выводящий в консоли “hello world!” преобразуется в .exe без проблем и все отлично работает. Проблемы начинаются если я пытаюсь преобразовать код с gui. Никаких сообщений об ошибках нет, exe-шник создается, но не работает. Я делаю так: python pyinstaller.py -w helloworld.py. Может здесь уже есть ошибка?
#10 Июнь 3, 2013 13:49:11
Запуск .py двойным щелчком в Windows7
vshnukrshna
Очень странно, у меня все собралось и нормально запустилось.
А вывод pyinstaller-а можно выложить?
Нет сегодняшних ошибок, есть вчерашние недоработки.
Источник: python.su
Статья Пакуем Python в EXE
Всем известно что питон это интерпретируемый, а не компилируемый язык . И в первую очередь рассчитан для работы в командной строке. Тем не менее, существует много вариантов оформления кода в GUI при необходимости. Но сегодня речь пойдёт об упаковке программы в EXE.
Зачем вообще это надо? Да по сути и не надо в большинстве случаев. Но бывает, что вы написали или скопировали какую-нибудь интересную тулзу, и хотите с ней поделиться. Конечно, если у того, кому вы отправляете прогу есть Python, то проблем нет. А бывает, что человек не шарит совсем в кодинге, и как пользователь тоже не имеет установленного питона нужной версии.
Вот тогда и выручает упаковка файла или файлов в EXE. Такой файл будет запускаться и работать по клику мышки, всё очень просто.
Для сборки файлов в экзешник есть разные приложения. Я рассмотрю самый простой, без всяких заморочек, с которым разберётся любой новичок.
Convert to EXE
Ссылка скрыта от гостей
Распаковываем архив. Внутри папки будет конвертер, запускающийся по клику мышки.
Так, нам понадобится подопытный. Для этого я сотряпал простой текстовый редактор, который открывает файл, и после редактирования сохраняет его. Ну или просто в окне можно что-то написать и сохранить.
# -*- coding:utf -8 -*- __version__ = ‘Version:1.0’ from tkinter import * from tkinter import filedialog as fd root = Tk() root.title(«Textedit » +str(__version__)) root.resizable(width=False, height=False) root.geometry(«420×300+300+300») calculated_text = Text(root,height=15, width=50) def insertText(): file_name = fd.askopenfilename() f = open(file_name) s = f.read() calculated_text.insert(1.0, s) f.close() def extractText(): file_name = fd.asksaveasfilename(filetypes=((«TXT files», «*.txt»), («HTML files», «*.html;*.htm»), («All files», «*.*») )) f = open(file_name, ‘w’) s = calculated_text.get(1.0, END) f.write(s) f.close() def erase(): calculated_text.delete(‘1.0′, END) b1 = Button(text=»Открыть»,command=insertText) b1.grid(row=3, column=0, sticky=E, padx=5, pady=8,) b2 = Button(text=»Сохранить», command=extractText) b2.grid(row=3, column=1, sticky=E, padx=5, pady=8,) erase_button = Button(text=»Очистить», command=erase) erase_button.grid(row=3, column=2, padx=35, pady=8, sticky=»W») scrollb = Scrollbar(root, command=calculated_text.yview) scrollb.grid(row=4, column=4, sticky=’nsew’) calculated_text.grid(row=4, column=0, sticky=’nsew’, columnspan=3) calculated_text.configure(yscrollcommand=scrollb.set) root.mainloop()
Запускаем прогу, так она выглядит
Выставляем следующие настройки -windowed чтобы прога запускалась без консоли, название выходного файла, onefile чтобы сборка была в один файл, noupx уже стоит по умолчанию ибо сжатие не всегда прокатывает. Ну и собственно выбираете нужный файл питоновский, который будете упаковывать. Также есть возможность выбрать иконку для exe-шника, поддерживается только ICO.
Вот что получилось
Жмём Build, прога чуток поколдует, выдаст нам сообщение об успешной сборке.
После этого в папке с конвертором появятся 2 папки
В папке dist и будет лежать наш готовый дистрибутив в формате EXE. Переместите его куда угодно, а потом обе эти папки можно смело удалять. Теперь проверяем работоспособность выходного файла, кликнув на него.
P.S. Редактор писался второпях, там есть косячок — при сохранении файла, расширение само не ставится, нужно вручную писать. Если кто поправит, буду признателен. Мне уже некогда, уезжаю отдыхать на 2 недели сейчас, так что на форуме меня не будет это время.
Последнее редактирование: 03.06.2019
explorer
Pentest Group
Platinum
explorer
Platinum
05.08.2018 1 093 2 510
exe файл уже получился, но открывается и командная строка..можно как то от строки избавиться?
Нужно читать внимательнее — процитирую сам себя:
Выставляем следующие настройки — windowed чтобы прога запускалась без консоли
LeMit
Member
20.02.2020 5 0
Всем доброго времени суток! Возникла проблема запуска из скомпилированного exe-файла других скриптов, написанных на питошке) Запускаю на компе, где не установлен питон. Скомпилированного exe-файл был собран через pyinstaller обычной командой: pyinstaller avtotest.py
в коде скомпилированного exe-файла запускаю другой скрипт написанный на питошке так:
def Adminnewpriglash(): subprocess.Popen(«python C:AvtotestAdminnewpriglash.py») adminmenu2.add_command(label=»Приглашения», command=Adminnewpriglash)
В скомпилированном exe-файле при нажатии на кнопку «Приглашения» получаю ошибку в консоли:
Exception in Tkinter callback Traceback (most recent call last): File «tkinter__init__.py», line 1705, in __call__ File «avtotest.py», line 159, in Adminnewpriglash File «subprocess.py», line 800, in __init__ File «subprocess.py», line 1207, in _execute_child FileNotFoundError: [WinError 2] Не удается найти указанный файл
Что нужно чтобы скрипты запускались? мб изменить код запуска? Есть вариант перекомпилить все скрипты в exe и уже запускать exe файлы из главного exe, но их достаточно много и отладка станет неудобной, поэтому ищу варианты как сделать действующий код рабочим)
explorer
Platinum
05.08.2018 1 093 2 510
Что нужно чтобы скрипты запускались?
Конечно же он никогда не запустится с таким кодом на другом компе. Откуда там возьмётся файл по адресу C:AvtotestAdminnewpriglash.py
LeMit
Member
20.02.2020 5 0
Конечно же он никогда не запустится с таким кодом на другом компе. Откуда там возьмётся файл по адресу C:AvtotestAdminnewpriglash.py
Благодарю за ответ) этот файл там есть естественно) он лежит прямо по такому же адресу, который и прописан в коде)
Алексей Шапошников
New member
20.02.2020 3 0
Конечно же он никогда не запустится с таким кодом на другом компе. Откуда там возьмётся файл по адресу C:AvtotestAdminnewpriglash.py
А если вот такое сообщение об ошибке (когда открываешь exe файл на компьютере без питона)? В чем проблема?
explorer
Platinum
05.08.2018 1 093 2 510
Благодарю за ответ) этот файл там есть естественно) он лежит прямо по такому же адресу, который и прописан в коде)
Это не поможет, так как интерпретатор python работает локально внутри exe. Нужно переписать программу, убрав внешнее подключение.
Посмотреть вложение 38560
А если вот такое сообщение об ошибке (когда открываешь exe файл на компьютере без питона)? В чем проблема?
Некорректная сборка, программа не видит отдельные модули библиотеки Tkinter. Пользуйтесь для сборки cx_Freeze, и прописывайте эти модули вручную, указав к ним путь.
LeMit
Member
20.02.2020 5 0
Это не поможет, так как интерпретатор python работает локально внутри exe. Нужно переписать программу, убрав внешнее подключение.
А как ее переписать не подскажите?
explorer
Platinum
05.08.2018 1 093 2 510
А как ее переписать не подскажите?
Если совсем коротко -внешнюю программу нужно положить в одну папку с основной программой, и подключить её как модуль import Adminnewpriglash но в основной программе ещё потребуются правки в коде, чтобы модуль работал. В общем гуглите Создание своего модуля.
LeMit
Member
20.02.2020 5 0
Если совсем коротко -внешнюю программу нужно положить в одну папку с основной программой, и подключить её как модуль import Adminnewpriglash но в основной программе ещё потребуются правки в коде, чтобы модуль работал. В общем гуглите Создание своего модуля.
Вызов был сделан так:
import Adminnewpriglash def avt3(): Adminnewpriglash.Admnewpriglash() adminmenu2.add_command(label=»avt3″, command=avt3)
только теперь при запуске главной программы сразу выполняется функция avt3, а она должна выполняться при нажатии на кнопку «avt3»
explorer
Platinum
05.08.2018 1 093 2 510
Вызов был сделан так:
import Adminnewpriglash def avt3(): Adminnewpriglash.Admnewpriglash() adminmenu2.add_command(label=»avt3″, command=avt3)
только теперь при запуске главной программы сразу выполняется функция avt3, а она должна выполняться при нажатии на кнопку «avt3»
В вашем коде я никакой кнопки вообще не вижу, по крайней мере этой части кода не выложено. А функция avt3 выполняется, потому что вы её вызываете, не нужно этого делать.
Вот вам простенькая программа с тремя кнопками, посмотрите как я сделал вызов функций кнопками.
Источник: codeby.net