2

Been playing around with pyinstaller and cx_freeze the last couple of days trying to get my app to run as a .exe.

In python everything works as intended.

I have the following items in a folder ready for compile...

files for compile

rawCodes.py is my main.

mcnc.py is my PyQt5 GUI.

mcnclogo_rc.py contains all the images i used in my GUI.

The following is a list of my imports in my main...

import sqlite3
from mcnc import Ui_MainWindow
import mcnclogo_rc
from PyQt5 import QtCore,QtGui,QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow, QTableWidgetItem, 
QDialog, QComboBox
import sys
import math

It seems that when i run pyinstaller it completes the process and produces 3 folders as expected.

The exe is clearly inside the dist folder and all appears to have worked.

However i run the exe and it just opens then closes again and nothing comes up.

I am convinced that my mcnc.py file is not being included and therefore i am not seeing a GUI (pyqt5).

Does anyone know how to specifically list mcnc.py in my SPEC file to make sure it is included...same with mcnclogo_rc.

EDIT

I have run the .exe from CMD and i am getting the following traceback...

G:\Yans work in progress\Yans python\Qt\to 
compile\dist\rawCodes>rawCodes.exe
Traceback (most recent call last):
File "rawCodes.py", line 3287, in <module>
File "rawCodes.py", line 22, in __init__
File "rawCodes.py", line 3101, in Load_StainlessDb
sqlite3.OperationalError: no such table: stainless
[13020] Failed to execute script rawCodes

Could it be that my database isnt getting packed properly in to the dist/build?

EDIT 2

I have changed the sqlite3 pathing so it is dynamic however it is still giving exactly the same error...

import sqlite3
import mcnc
from mcnc import Ui_MainWindow
import mcnclogo_rc
from PyQt5 import QtCore,QtGui,QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow, QTableWidgetItem, 
QDialog, QComboBox
import sys
import math
import os

package_dir = os.path.abspath(os.path.dirname(__file__))
db_dir = os.path.join(package_dir, 'codes.db')
print(db_dir)

conn = sqlite3.connect(db_dir)
c = conn.cursor()
c.execute('')

def stainless_list(self):
    stainless_getlist = []

    content = 'SELECT grade FROM stainless ORDER BY prefix ASC'
    res = conn.execute(content)
    for row in res:
        stainless_getlist.append(row[0])

    conn.close

    stainless_getlist.insert(0, "Select...")
    self.comboBox_2.clear()
    self.comboBox_2.addItems(stainless_getlist)

    #print(stainless_getlist)
    return

Then i still get the following error...

G:\Yans work in progress\Yans python\Qt\to 
compile\dist\rawCodes>rawCodes.exe
Traceback (most recent call last):
  File "rawCodes.py", line 3287, in <module>
  File "rawCodes.py", line 22, in __init__
  File "rawCodes.py", line 3101, in Load_StainlessDb
sqlite3.OperationalError: no such table: stainless
[14664] Failed to execute script rawCodes

EDIT 3

Here is the print of my dir paths once compiled...

G:\Yans work in progress\Yans python\Qt\to 
compile\dist\rawCodes>rawCodes.exe
G:\Yans work in progress\Yans python\Qt\to compile\dist\rawCodes
G:\Yans work in progress\Yans python\Qt\to compile\dist\rawCodes\codes.db

Here is my code and imports...

import sqlite3
import mcnc
from mcnc import Ui_MainWindow
import mcnclogo_rc
from PyQt5 import QtCore,QtGui,QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow, QTableWidgetItem, 
QDialog, QComboBox
import sys
import math
import os
import os.path as op

try:
    this_file = __file__
except NameError:
    this_file = sys.argv[0]
this_file = op.abspath(this_file)
if getattr(sys, 'frozen', False):
    application_path = getattr(sys, '_MEIPASS', 
    op.dirname(sys.executable))
else:
    application_path = op.dirname(this_file)

sqlite_conn = os.path.join(application_path, 'codes.db')

print(application_path)
print(sqlite_conn)

conn = sqlite3.connect(sqlite_conn)
c = conn.cursor()
c.execute('')

but once compiled and trying to run from the dist it can no longer see the tables in the db.

EDIT 4

I changed my code to the following...

import sqlite3
import mcnc
from mcnc import Ui_MainWindow
import mcnclogo_rc
from PyQt5 import QtCore,QtGui,QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow, QTableWidgetItem, 
QDialog, QComboBox
import sys
import math
import os
import os.path as op

try:
    this_file = __file__
except NameError:
    this_file = sys.argv[0]
this_file = op.abspath(this_file)
if getattr(sys, 'frozen', False):
    application_path = getattr(sys, '_MEIPASS', op.dirname(sys.executable))
else:
    application_path = op.dirname(this_file)

sqlite_conn = os.path.join(QApplication.applicationDirPath(), 'codes.db')

print(application_path)
print(sqlite_conn)

conn = sqlite3.connect(sqlite_conn)
c = conn.cursor()
c.execute('')

I now get the following traceback...

G:\Yans work in progress\Yans python\Qt\to 
compile\dist\rawCodes>rawCodes.exe
QCoreApplication::applicationDirPath: Please instantiate the QApplication 
object first
G:\Yans work in progress\Yans python\Qt\to compile\dist\rawCodes
codes.db
Traceback (most recent call last):
  File "rawCodes.py", line 3303, in <module>
  File "rawCodes.py", line 38, in __init__
  File "rawCodes.py", line 3117, in Load_StainlessDb
sqlite3.OperationalError: no such table: stainless
[3268] Failed to execute script rawCodes

EDIT 5

app = QApplication(sys.argv)

sqlite_conn = os.path.join(QApplication.applicationDirPath(), 'codes.db')

G:\Yans work in progress\Yans python\Qt
C:/Program Files (x86)/Python37-32\codes.db

Got a straight up error and couldnt connect to the db at all. The db folder now points to C: drive.

Yan
  • 161
  • 1
  • 13
  • 1
    Use the full path of the .db – eyllanesc Apr 18 '19 at 03:22
  • 1
    read https://stackoverflow.com/questions/404744/determining-application-path-in-a-python-exe-generated-by-pyinstaller – eyllanesc Apr 18 '19 at 18:56
  • try with: `sqlite_conn = os.path.join(QApplication.applicationDirPath(), 'codes.db')` – eyllanesc Apr 18 '19 at 19:38
  • add `app = QApplication(sys.argv)` before `sqlite_conn = ...` – eyllanesc Apr 18 '19 at 21:12
  • I think it is worth adding that the codes.db file is packed in to the .exe after compile. On clicking the .exe the codes.db file pops out in to the same directory as the .exe....not sure if this may be the reason that it cant connect to the tables. – Yan Apr 18 '19 at 23:55

3 Answers3

1

After many hours i noticed that the script was failing at the point where it tried to access the tables of the db and not at the connect statement in my compile.

Upon further inspection i noticed that after the compile has run the codes.db was missing until i clicked the .exe to run. Then a codes.db popped out of the exe with 0kb and no tables.

I have concluded that i need to research how to include the original .db file in the compile and not allow it to create a new empty .db in its absence.

I have tested this by over writing the empty .db with the original .db and suddenly my .exe works perfectly.

Yan
  • 161
  • 1
  • 13
  • I also encourage you to use sqlite via sqlalchemy. I did not have any issue with dbs or having to fix hidden imports. This SO question is an illustration: https://stackoverflow.com/questions/47114772/sqlite-pyqt5-to-standalone-exe-python-3-6-3-pyinstaller – Abdur-Rahmaan Janhangeer Jan 15 '20 at 08:31
1

I believe the answer is simple. Let's analyse the stacktrace

enter image description here

The red part is the error name: OperationalError. From the docs:

Exception raised for errors that are related to the database’s operation and not necessarily under the control of the programmer, e.g. an unexpected disconnect occurs, the data source name is not found, a transaction could not be processed, etc. It is a subclass of DatabaseError.

But, the green part tells us:

no such table: stainless

which simply means the table is not found as it was either deleted or it was not created at all.

And, as far as i can see, no table creation code is to be found. It's not a PyInstaller error.

0

Your exe closes then opens up because you have no body code. In your main code's body add this:

input()

That should fix it.

xilpex
  • 3,097
  • 2
  • 14
  • 45
  • I do not think that your code does not have a body but that the OP considers that the information that is needed to reproduce the problem is only the imports of the modules that it uses. – eyllanesc Apr 17 '19 at 23:14
  • i have nearly 1000 lines of code in rawCodes.py (my main py). It runs perfectly in python. – Yan Apr 17 '19 at 23:53