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...
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.
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.
I believe the answer is simple. Let's analyse the stacktrace
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.
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.
Related
I'm trying build an executable of a Python script that reads from a digital multimeter connected via RS232-USB. To build, I'm using cxfreeze.
For this, a setup.py file was written to management. When I run the Python script, everything happens normally. But the built executable doesn't run and shows: ValueError: Could not locate a VISA implementation. Install either the IVI binary or pyvisa-py.
I wrote a simpler code to test, including all the used packages of the main program, but the executable file shows the same error.
The code (test_pyvisa_implementation.py) is:
from matplotlib.figure import Figure
import tkinter as tk
from tkinter import *
import numpy as np
import time, warnings
import pyvisa as visa
from tkinter import filedialog
def port_send():
global ports
print(ports.get())
window = tk.Tk()
window.title("Testing pyvisa implementation")
baudRate = 19200
flowCtrl = visa.constants.VI_ASRL_FLOW_NONE
rm = visa.ResourceManager()
com = rm.list_resources()
if com == ():
com = ['No connection']
ports = tk.StringVar(window)
def refresh_port(ports):
ports.set('')
w['menu'].delete(0, 'end')
com = rm.list_resources()
print(com)
if com == ():
com = ['No connection']
for choices in com:
w['menu'].add_command(label=com, command=tk._setit(ports, choices))
w = tk.OptionMenu(window, ports, *com)
w.place(x = 50, y = 0)
refresh = tk.Button(window, text='refresh', command = lambda:refresh_port(ports))
refresh.place(x = 50, y = 80)
confirm = tk.Button(window, text="Confirm", command = lambda:port_send())
confirm.place(x = 50, y = 160)
window.mainloop()
The setup.py is:
import os
from cx_Freeze import setup, Executable
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import tkinter as tk
from tkinter import *
import numpy as np
import time, warnings
import pyvisa as visa
from tkinter import filedialog
base = None
executables = [
Executable("test_pyvisa_implementation.py", base=base)
]
buildOptions = dict(
packages = ['matplotlib.backends.backend_tkagg','matplotlib.figure',\
'tkinter','numpy','time','pyvisa'],
includes = [],
include_files = [],
excludes = []
)
setup(
name = "TESTING_PYVISA_IMPLEMENTATION",
version = "1.0",
description = "DEFAULT",
options = dict(build_exe = buildOptions),
executables = executables
)
The error is:
> Traceback (most recent call last):
File "/home/lcem/.platformio/penv/lib/python3.8/site-packages/cx_Freeze/initscripts/__startup__.py", line 113, in run
module_init.run(name + "__main__")
File "/home/lcem/.platformio/penv/lib/python3.8/site-packages/cx_Freeze/initscripts/Console.py", line 15, in run
exec(code, module_main.__dict__)
File "test_pyvisa_implementation.py", line 21, in <module>
File "/home/lcem/.platformio/penv/lib/python3.8/site-packages/pyvisa/highlevel.py", line 3015, in __new__
visa_library = open_visa_library(visa_library)
File "/home/lcem/.platformio/penv/lib/python3.8/site-packages/pyvisa/highlevel.py", line 2924, in open_visa_library
wrapper = _get_default_wrapper()
File "/home/lcem/.platformio/penv/lib/python3.8/site-packages/pyvisa/highlevel.py", line 2883, in _get_default_wrapper
raise ValueError(
ValueError: Could not locate a VISA implementation. Install either the IVI binary or pyvisa-py.
Even if I reinstall the pyvisa-py package, I still get the error.
Any suggestions what I can do?
My system information: Linux 5.4.0-90-generic #101-Ubuntu SMP Fri Oct 15 20:00:55 UTC 2021.
I created an executable using pyinstaller. My scripts all run fine but when i run the executable i get the error below. It appears it doesnt like the mysql connector in DBconnection.py. Any help is appreciated.
Traceback (most recent call last):
File "main.py", line 8, in
File "c:\programdata\anaconda3\lib\site-packages\PyInstaller\loader\pyimod03_i
mporters.py", line 631, in exec_module
File "DBconnection.py", line 2, in
ModuleNotFoundError: No module named 'mysql'
[4780] Failed to execute script main
DBconnection.py:
from configparser import ConfigParser
from mysql.connector import MySQLConnection
import Global
def create_db_connection(filename= 'my.ini', section= 'dbconnection'):
parser = ConfigParser()
parser.read(filename)
db = {}
if parser.has_section(section):
items = parser.items(section)
for item in items:
db[item[0]] = item[1]
else:
raise Exception('{0} not found in the {1} file'.format(section. filename))
#global conn
Global.conn = MySQLConnection(**db)
print(Global.conn)
def close_db_connection():
Global.conn.close()
main.py:
from servers import updateservers
from policies import updatepolicies
from updateguardpoints import updateguardpoints
from activities import updateactivities
from guardpointstatus import updateguardpointstatus
from application import updateapplication
from application_servers import updateapplication_servers
from DBconnection import create_db_connection
from DBconnection import close_db_connection
from TrouxConnection import TrouxConnection
from TrouxConnection import CloseTrouxConnection
import Global
create_db_connection()
TrouxConnection()
updateservers()
updatepolicies()
updateguardpoints()
updateactivities()
updateguardpointstatus()
updateapplication()
updateapplication_servers()
CloseTrouxConnection()
close_db_connection()
reinstalled mysql - connector using PIP. Issue resolved
Traceback (most recent call last):
File "bs4.py", line 1, in <module>
import bs4
File "/home/mhadi/Desktop/bs4test/bs4.py", line 5, in <module>
soup = bs4.BeautifulSoup(site,'lxml')
AttributeError: module 'bs4' has no attribute 'BeautifulSoup'
The code:
import bs4
import urllib.request
site = urllib.request.urlopen('http://127.0.0.1:8000').read()
soup = bs4.BeautifulSoup(site,'lxml')
#for i in site:
# print(site[i])
print(soup)
The problem is that your filename is bs4.py. Now if you write an import statement, Python will first look for local files with that name. So it assumes that your import bs4 refers to your own file. Your file will thus aim to import itself, but it obviously does not contain the desired module.
A quick fix is renaming the file. For instance into bs4tests.py. Then you can use import bs4.
Alternatively, you can for instance try to remove the local path, like:
import sys # import sys package
old_path = sys.path[:] # make a copy of the old paths
sys.path.pop(0) # remove the first one (usually the local)
import bs4 # import the package
sys.path = old_path # restore the import path
I am trying to generate an HTML test report by using Selenium webdriver library HTMLTestRunner. I am using Python 3.4 version and I have a version related error. Refer following snippet.
import unittest`enter code here`
import HTMLTestRunner
from selenium import webdriver
from selenium.webdriver.common.alert import Alert
from selenium.webdriver.common.keys import Keys
class GreenlamTest(unittest.TestCase):
#classmethod
def setUp(cls):
cls.driver=webdriver.Firefox()
cls.driver.implicitly_wait(30)
cls.driver.maximize_window()
cls.driver.get('https://www.google.co.in')
def test_checkTitle(self):
assert "Google" in self.driver.title
def test_searchtest(self):
driver = self.driver
elem = self.driver.find_element_by_name("q")
elem.send_keys("pycon")
elem.send_keys(Keys.RETURN)
#classmethod
def tearDown(cls):
cls.driver.quit()
if __name__ == '__main__':
HTMLTestRunner.main
Output
Finding files... done.
Traceback (most recent call last):
File "C:\Users\vaibhav\Desktop\Selenium Softwares\eclipse-jee-luna-SR2-win32-x86_64\eclipse\plugins\org.python.pydev_4.0.0.201504132356\pysrc\pydev_runfiles.py", line 468, in __get_module_from_str
mod = __import__(modname)
File "C:\Users\vaibhav\Desktop\Selenium Softwares\Practice\pythondemo\Htmlreport.py", line 2, in <module>
import HTMLTestRunner
File "C:\Users\vaibhav\Desktop\Selenium Softwares\Practice\pythondemo\HTMLTestRunner.py", line 94, in <module>
import StringIO
ImportError: No module named 'StringIO'
ERROR: Module: Htmlreport could not be imported (file: C:\Users\vaibhav\Desktop\Selenium Softwares\Practice\pythondemo\Htmlreport.py).
Importing test modules ... done.
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
You are getting error because your folder name Selenium Softwares has a space in it where your Htmlreport is present. Replace the folder name to exclude space out of it, probably an underscore or camelCase, etc... like this Selenium_Softwares . Here's how -
file: C:\Users\vaibhav\Desktop\Selenium_Softwares\Practice\pythondemo\Htmlreport.py)
Hope this helps.
I use CX_Freeze to freeze one of my python programs. The build system works fine in windows. I can create a directory with executable and necessary dependencies that will run in any windows system.
When I try the same in Linux, the building part
python setup.py
works fine. But when I try to run the built executable, its gives the following error.
File "/usr/local/lib/python2.7/dist-packages/cx_Freeze/initscripts/Console.py", line 27, in <module>
exec code in m.__dict__
File "test.py", line 1, in <module>
File "/usr/local/lib/python2.7/dist-packages/guidata/__init__.py", line 540, in <module>
import guidata.config
File "/usr/local/lib/python2.7/dist-packages/guidata/config.py", line 19, in <module>
add_image_module_path("guidata", "images")
File "/usr/local/lib/python2.7/dist-packages/guidata/configtools.py", line 100, in add_image_module_path
add_image_path(get_module_data_path(modname, relpath=relpath), subfolders)
File "/usr/local/lib/python2.7/dist-packages/guidata/configtools.py", line 86, in add_image_path
for fileobj in os.listdir(path):
OSError: [Errno 20] Not a directory: '/home/user/tmp/dist/library.zip/guidata/images'
It seems that guidata is trying to find images under non-existing library.zip/guidata/images directory. I made sure that I run same versions of guidata, cx_Freeze on both windows and linux. Any help to resolve the issue is appreciated.
Minimal example
import guidata
_app = guidata.qapplication() # not required if a QApplication has already been created
import guidata.dataset.datatypes as dt
import guidata.dataset.dataitems as di
class Processing(dt.DataSet):
"""Example"""
a = di.FloatItem("Parameter #1", default=2.3)
b = di.IntItem("Parameter #2", min=0, max=10, default=5)
type = di.ChoiceItem("Processing algorithm",
("type 1", "type 2", "type 3"))
param = Processing()
param.edit()
setup file
import sys
import os
"""Create a stand-alone executable"""
try:
import guidata
from guidata.disthelpers import Distribution
except ImportError:
raise ImportError, "This script requires guidata 1.4+"
def create_executable():
"""Build executable using ``guidata.disthelpers``"""
dist = Distribution()
dist.setup(name='Foo', version='0.1',
description='bar',
script="test.py", target_name='test.exe')
dist.add_modules('guidata', 'guiqwt')
# Building executable
dist.build('cx_Freeze')
if __name__ == '__main__':
create_executable()
OK. Here's the answer to my own question. After much digging up, I realized that it is a bug in guidata and/or python's os.path module. What happens is this. On guidata module, in configtools.py file, there is a function get_module_data_path, that checks whether the parent 'directory' of a path like /foo/bar/library.zip/yap to be a file.
import os.path as osp
...
...
datapath = get_module_path(modname)
parentdir = osp.join(datapath, osp.pardir)
if osp.isfile(parentdir):
# Parent directory is not a directory but the 'library.zip' file:
# this is either a py2exe or a cx_Freeze distribution
datapath = ...
Now the test
osp.isfile("/foo/bar/library.zip/yap/..")
returns True in windows but False in Linux. This breaks the code. Python documentation is unclear in stating whether this is a bug or the intended behavior.
At the moment I don't have a solution, but a hack. I changed the above code as:
import os.path as osp
...
...
datapath = get_module_path(modname)
parentdir = osp.join(datapath, osp.pardir)
parentdir2 = osp.split(datapath.rstrip(os.path.sep))[0]
if osp.isfile(parentdir) or osp.isfile(parentdir2):
# Parent directory is not a directory but the 'library.zip' file:
# this is either a py2exe or a cx_Freeze distribution
datapath = ...
and everything is fine.