Вообщим, все началось с того, что я начал изучать язык Python, понравился он мне моментально (перед этим работал только с С++). Я продолжил потихоньку изучать Python, и тут я решил написать что-то полезное для общества, так сказать. Тут же мой друг/начальник/коллега попросил написать програмку для подсчета стоимости печати на плотере (я подрабатываю в фотостудии/рекламном агенстве), я сразу решил делать это приложение не консольным, а в окне (заодно научился работать с PyQt4). Вообщим сначала я очень уж долго розбирался в PyQt, перелапатил наверное 3/4 всего интернета… Все-таки осилил и получилось вот что — 
, НО тут я понял, что использоваться это будет и на других машинах, кроме моей, а там 99% вероятности что нету интерпритатора Python'a…
Что делать? Конечто же загнать это все дело в EXEшник и дело с концами! Сразу обратился к Хабру, вычитал про py2exe, решил и использовать эту утилиту.
Все сначала как обычно — устанавливаем py2exe, создаем setup.py в директории с нашей програмкой в .py, потом cmd($ setup.py py2exe) и получаем две папки, одна из них не нужна для роботы программы, во второй же и лежит сам EXEшник с кучей иных файлов

, взял всю эту папку (она по умолчанию называется dist) и скинул на ноут с Windows XP (сам то я пользую 7 Professional N), запускаю мой EXEшник, и ура, заработало!!!
Но я решил на этом не останавливаться — меня не радовала маленькая програмка в виде папки с кучей файлов. И тут понеслась — я перечитал все статьи на Хабре, много пробовал, не плучалось, потом нашел еще один САЙТ, на нем уж я «погулял» очень даже не мало… Вообщим, этими усилиями я добился того что мне py2exe выдавал три файла в сmd ($ setup.py py2exe -b 2, но при этом в setup.py в модуль «includes» нужно добавить импортируемые програмой файлы/библиотеки и еще после опций «zipfile=None») — сам EXEшник, EXEшник для Windows 98 и старше и одну DLLку а именно python27.dll

, как я в в самом файле setup.py не извращался, но не смог добиться того чтобы py2exe впихивал и эту DLLку в EXEшник… И тут я решил сделать «шаг конем» — поскольку я в setup.py и так подгружаю PyQt4 библиотеки, почему бы не сделать этот самый python27.dll библиотекой PyQt4? Я взял эту python27.dll и скопировал в ..\Python27\Lib\site-packages\PyQt4 потом запускаем $ setup.py py2exe -b 1 и получаем готовый EXEшник

, работающий на других машинах, без установки чего-либо!
Готовый EXEшник скачать можно здесь
Вот код setup.py:
Где «Sindaria_Ploter_print.py» это вот:
Файл qad представляет собой вот это:
Вот dialog.py:
Все эти 4 скрипта (Sindaria_Ploter_print.py, setup.py,
Конечно код пугает меня самого, но я здесь не о коде пишу, а каким образом смог добиться полного «упаковывания» моейго скрипта.py в .EXE
P.S кто решит впервые пробовать py2exe после этой статьи, то команда py2exe в cmd исполняеться находясь в директории с самим setup.py
P.P.S файл «w9xpopen.exe» можете более чем смело удалять, он не влияет на работоспособность основной_програмы.exe

, НО тут я понял, что использоваться это будет и на других машинах, кроме моей, а там 99% вероятности что нету интерпритатора Python'a…
Что делать? Конечто же загнать это все дело в EXEшник и дело с концами! Сразу обратился к Хабру, вычитал про py2exe, решил и использовать эту утилиту.
Все сначала как обычно — устанавливаем py2exe, создаем setup.py в директории с нашей програмкой в .py, потом cmd($ setup.py py2exe) и получаем две папки, одна из них не нужна для роботы программы, во второй же и лежит сам EXEшник с кучей иных файлов

, взял всю эту папку (она по умолчанию называется dist) и скинул на ноут с Windows XP (сам то я пользую 7 Professional N), запускаю мой EXEшник, и ура, заработало!!!
Но я решил на этом не останавливаться — меня не радовала маленькая програмка в виде папки с кучей файлов. И тут понеслась — я перечитал все статьи на Хабре, много пробовал, не плучалось, потом нашел еще один САЙТ, на нем уж я «погулял» очень даже не мало… Вообщим, этими усилиями я добился того что мне py2exe выдавал три файла в сmd ($ setup.py py2exe -b 2, но при этом в setup.py в модуль «includes» нужно добавить импортируемые програмой файлы/библиотеки и еще после опций «zipfile=None») — сам EXEшник, EXEшник для Windows 98 и старше и одну DLLку а именно python27.dll

, как я в в самом файле setup.py не извращался, но не смог добиться того чтобы py2exe впихивал и эту DLLку в EXEшник… И тут я решил сделать «шаг конем» — поскольку я в setup.py и так подгружаю PyQt4 библиотеки, почему бы не сделать этот самый python27.dll библиотекой PyQt4? Я взял эту python27.dll и скопировал в ..\Python27\Lib\site-packages\PyQt4 потом запускаем $ setup.py py2exe -b 1 и получаем готовый EXEшник

, работающий на других машинах, без установки чего-либо!
Готовый EXEшник скачать можно здесь
Вот код setup.py:
from distutils.core import setup
import py2exe
setup(
windows=[{"script":"Sindaria_Ploter_print.py"}],
options={"py2exe": {"includes":["sip","qad","dialog","sys","PyQt4"]}},
zipfile=None
)
Где «Sindaria_Ploter_print.py» это вот:
import sys
import dialog
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4 import QtCore, QtGui
import qad
class MyClass(QDialog, dialog.Ui_Dialog):
def __init__(self, parent=None):
QDialog.__init__(self,parent)
self.setupUi(self)
self.connect(self.pushButton, SIGNAL("clicked()"), self.actionOnButton)
self.connect(self.pushButton_2,QtCore.SIGNAL("clicked()"),QtCore.SLOT('close()'))
self.checkBox_2.setEnabled(False)
self.checkBox.setEnabled(False)
self.connect(self.radioButton,QtCore.SIGNAL("toggled(bool)"),self.onbtn)
self.connect(self.radioButton_2,QtCore.SIGNAL("toggled(bool)"),self.ofbtn)
self.connect(self.radioButton_3,QtCore.SIGNAL("toggled(bool)"),self.ofbtn)
def onbtn(self):
self.checkBox_2.setEnabled(True)
self.checkBox.setEnabled(True)
def ofbtn(self):
self.checkBox_2.setChecked(False)
self.checkBox_2.setEnabled(False)
self.checkBox.setChecked(False)
self.checkBox.setEnabled(False)
def actionOnButton(self):
p=0
k=0
if self.checkBox_2.isChecked():
p=1
if self.checkBox.isChecked():
k=1
if self.radioButton.isChecked():
l=1
if self.radioButton_2.isChecked():
l=2
if self.radioButton_3.isChecked():
l=3
x=int(self.lineEdit.text())
y=int(self.lineEdit_2.text())
v = qad._set(x,y,int(self.spinBox.value()),l)
if l==1:
r=v*2.4
else:
r=v*2
v=str(v)
r=r-(r*(int(self.spinBox_2.value()))*0.01)
if p==1:
if k==1:
r=r+((x+y)*0.05)+((x*y*0.045)/1000)
else:
r=r+((x+y)*0.05)
r=str(r)
self.label_5.setText(v)
self.label_8.setText(r)
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MyClass()
w.show()
app.exec_()
Файл qad представляет собой вот это:
def _set(x,y,o,z):
k=(y*x)*0.02
k=(k*0.29)+(k*0.7)
if z==1 :
l=k+(x*y*(0.0536+0.03))
if z==2 :
l=k+(x*y*(0.0099+0.03))
if z==3 :
l=k+(x*y*(0.02156+0.03))
l=l/1000
l=l*o
return l
Вот dialog.py:
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName(_fromUtf8("Dialog"))
Dialog.resize(417, 176)
self.lineEdit = QtGui.QLineEdit(Dialog)
self.lineEdit.setGeometry(QtCore.QRect(10, 20, 113, 20))
self.lineEdit.setObjectName(_fromUtf8("lineEdit"))
self.lineEdit_2 = QtGui.QLineEdit(Dialog)
self.lineEdit_2.setGeometry(QtCore.QRect(10, 50, 113, 20))
self.lineEdit_2.setObjectName(_fromUtf8("lineEdit_2"))
self.groupBox = QtGui.QGroupBox(Dialog)
self.groupBox.setGeometry(QtCore.QRect(200, 20, 120, 111))
self.groupBox.setObjectName(_fromUtf8("groupBox"))
self.radioButton = QtGui.QRadioButton(self.groupBox)
self.radioButton.setGeometry(QtCore.QRect(20, 20, 82, 17))
self.radioButton.setObjectName(_fromUtf8("radioButton"))
self.radioButton_2 = QtGui.QRadioButton(self.groupBox)
self.radioButton_2.setGeometry(QtCore.QRect(20, 50, 82, 17))
self.radioButton_2.setObjectName(_fromUtf8("radioButton_2"))
self.radioButton_3 = QtGui.QRadioButton(self.groupBox)
self.radioButton_3.setGeometry(QtCore.QRect(20, 80, 82, 17))
self.radioButton_3.setObjectName(_fromUtf8("radioButton_3"))
self.label = QtGui.QLabel(Dialog)
self.label.setGeometry(QtCore.QRect(140, 20, 46, 13))
self.label.setObjectName(_fromUtf8("label"))
self.label_2 = QtGui.QLabel(Dialog)
self.label_2.setGeometry(QtCore.QRect(140, 50, 46, 13))
self.label_2.setObjectName(_fromUtf8("label_2"))
self.label_3 = QtGui.QLabel(Dialog)
self.label_3.setGeometry(QtCore.QRect(60, 80, 46, 13))
self.label_3.setObjectName(_fromUtf8("label_3"))
self.spinBox = QtGui.QSpinBox(Dialog)
self.spinBox.setGeometry(QtCore.QRect(10, 80, 42, 22))
self.spinBox.setMinimum(1)
self.spinBox.setObjectName(_fromUtf8("spinBox"))
self.pushButton = QtGui.QPushButton(Dialog)
self.pushButton.setGeometry(QtCore.QRect(230, 140, 75, 23))
self.pushButton.setObjectName(_fromUtf8("pushButton"))
self.pushButton_2 = QtGui.QPushButton(Dialog)
self.pushButton_2.setGeometry(QtCore.QRect(330, 140, 75, 23))
self.pushButton_2.setObjectName(_fromUtf8("pushButton_2"))
self.label_4 = QtGui.QLabel(Dialog)
self.label_4.setGeometry(QtCore.QRect(10, 120, 71, 16))
self.label_4.setObjectName(_fromUtf8("label_4"))
self.label_5 = QtGui.QLabel(Dialog)
self.label_5.setGeometry(QtCore.QRect(110, 140, 46, 13))
self.label_5.setText(_fromUtf8(""))
self.label_5.setObjectName(_fromUtf8("label_5"))
self.checkBox_2 = QtGui.QCheckBox(Dialog)
self.checkBox_2.setGeometry(QtCore.QRect(330, 50, 70, 17))
self.checkBox_2.setObjectName(_fromUtf8("checkBox_2"))
self.label_6 = QtGui.QLabel(Dialog)
self.label_6.setGeometry(QtCore.QRect(340, 30, 71, 16))
self.label_6.setObjectName(_fromUtf8("label_6"))
self.label_7 = QtGui.QLabel(Dialog)
self.label_7.setGeometry(QtCore.QRect(10, 140, 91, 16))
self.label_7.setObjectName(_fromUtf8("label_7"))
self.label_8 = QtGui.QLabel(Dialog)
self.label_8.setGeometry(QtCore.QRect(110, 120, 46, 13))
self.label_8.setText(_fromUtf8(""))
self.label_8.setObjectName(_fromUtf8("label_8"))
self.label_9 = QtGui.QLabel(Dialog)
self.label_9.setGeometry(QtCore.QRect(140, 80, 51, 16))
self.label_9.setObjectName(_fromUtf8("label_9"))
self.spinBox_2 = QtGui.QSpinBox(Dialog)
self.spinBox_2.setGeometry(QtCore.QRect(100, 80, 42, 22))
self.spinBox_2.setMinimum(0)
self.spinBox_2.setProperty("value", 0)
self.spinBox_2.setObjectName(_fromUtf8("spinBox_2"))
self.checkBox = QtGui.QCheckBox(Dialog)
self.checkBox.setGeometry(QtCore.QRect(330, 70, 70, 17))
self.checkBox.setObjectName(_fromUtf8("checkBox"))
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
Dialog.setWindowTitle(QtGui.QApplication.translate("Dialog", "Cost calc", None, QtGui.QApplication.UnicodeUTF8))
self.groupBox.setTitle(QtGui.QApplication.translate("Dialog", "Материал", None, QtGui.QApplication.UnicodeUTF8))
self.radioButton.setText(QtGui.QApplication.translate("Dialog", "Холст", None, QtGui.QApplication.UnicodeUTF8))
self.radioButton_2.setText(QtGui.QApplication.translate("Dialog", "Бумага", None, QtGui.QApplication.UnicodeUTF8))
self.radioButton_3.setText(QtGui.QApplication.translate("Dialog", "Ткань", None, QtGui.QApplication.UnicodeUTF8))
self.label.setText(QtGui.QApplication.translate("Dialog", "Высота", None, QtGui.QApplication.UnicodeUTF8))
self.label_2.setText(QtGui.QApplication.translate("Dialog", "Ширина", None, QtGui.QApplication.UnicodeUTF8))
self.label_3.setText(QtGui.QApplication.translate("Dialog", "Копий", None, QtGui.QApplication.UnicodeUTF8))
self.pushButton.setText(QtGui.QApplication.translate("Dialog", "Просчитать", None, QtGui.QApplication.UnicodeUTF8))
self.pushButton_2.setText(QtGui.QApplication.translate("Dialog", "Выход", None, QtGui.QApplication.UnicodeUTF8))
self.label_4.setText(QtGui.QApplication.translate("Dialog", "Стоимость :", None, QtGui.QApplication.UnicodeUTF8))
self.checkBox_2.setText(QtGui.QApplication.translate("Dialog", "Натяжка", None, QtGui.QApplication.UnicodeUTF8))
self.label_6.setText(QtGui.QApplication.translate("Dialog", "Для холста :", None, QtGui.QApplication.UnicodeUTF8))
self.label_7.setText(QtGui.QApplication.translate("Dialog", "Себестоимость :", None, QtGui.QApplication.UnicodeUTF8))
self.label_9.setText(QtGui.QApplication.translate("Dialog", "% скидка", None, QtGui.QApplication.UnicodeUTF8))
self.checkBox.setText(QtGui.QApplication.translate("Dialog", "Лак", None, QtGui.QApplication.UnicodeUTF8))
Все эти 4 скрипта (Sindaria_Ploter_print.py, setup.py,
Конечно код пугает меня самого, но я здесь не о коде пишу, а каким образом смог добиться полного «упаковывания» моейго скрипта.py в .EXE
P.S кто решит впервые пробовать py2exe после этой статьи, то команда py2exe в cmd исполняеться находясь в директории с самим setup.py
P.P.S файл «w9xpopen.exe» можете более чем смело удалять, он не влияет на работоспособность основной_програмы.exe