According to the official documentation of multiprocessing:
Calling freeze_support() has no effect when invoked on any operating system other than Windows.
But in fact, I found that freeze_support is actually essential when we create an executable file with pyinstaller on macOS. Here is a simple example script to demonstrate:
import multiprocessing
def child():
print("In CHILD")
def main():
input("In MAIN")
pool = multiprocessing.Pool(processes=1)
input("Pool initialized, Press ENTER to continue")
pool.apply(child)
print("Child exited")
if __name__ == '__main__':
print("Program Started")
main()
If we compile this code with the command, pyinstaller main.py, and run the resultant executable file, after we press ENTER for the line of input calls, the program will create a child process that also runs the code inside if __name__ == '__main__'. This behavior is not as expected.
Example output (in fact it just keep looping):
Program Started
In MAIN
Pool initialized, Press ENTER to continueProgram Started
In MAINProgram Started
In MAIN
Pool initialized, Press ENTER to continueProgram Started
In MAINProgram Started
In MAIN
Pool initialized, Press ENTER to continueProgram Started
In MAINProgram Started
In MAIN
Pool initialized, Press ENTER to continueProgram Started
In MAINProgram Started
In MAIN
But if we add multiprocessing.freeze_support() in if __name__ == '__main__', this issue solves. The executable file can run as expected, like how it runs in an IDE.
i.e.
if __name__ == '__main__':
multiprocessing.freeze_support()
print("Program Started")
main()
Example output of an expected run:
Program Started
In MAIN
Pool initialized, Press ENTER to continue
In CHILD
Child exited
Thus, I would like to ask, why freeze_support is still essential for an executable file on macOS, even though the official documentation says it only has an effect on Windows. (It takes a long time for me to solve this issue, since I thought freeze_support is not related to macOS at all)
Testing Environment:
macOS 13.2 (ARM)
Python 3.10
pyinstaller 5.8.0
Related
I've recently started learning python and am still a newbie.
How can I determine if my code run from IDE or run standalone?
My code is not imported so
__name__ == "__main__" .
Someone suggested checking sys.executable name but I'm looking for a solution independent of the file name.
P.S: I create a standalone file with pyinstaller.
Here's a link to the page pyinstaller has on their site giving information about how to check the Run-Time information of your file: https://pyinstaller.org/en/stable/runtime-information.html
Basically it says to add the following code
import sys
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
print('running in a PyInstaller bundle')
else:
print('running in a normal Python process')
This should print the 'running in a PyInstaller bundle' message if it's all self contained and properly bundled, and it should print 'running in a normal Python process' if it's still running from your source code.
I have a simple script that calls other scripts and works fine:
def demandesparbranche():
os.system('python Sources/x.py')
def demandesparlogiciel():
os.system('python Sources/xx.py')
def demandeshcapprouvees():
os.system('python Sources/xxx.py')
def challengesreussis():
os.system('python Sources/xxxx.py')
My idea was to add a GUI with tkinter and freeze this code (with pyinstaller) and use it as a set of buttons to launch the scripts that would in this way remain modifiable. I tried and it does not work, which is logical since in a computer without python installed the command 'python' is obviously unknown. The code works fine in my computer where python is installed.
Is this in any way possible using possibly another form of script calling? What I mean is: how to call the Python interpreter frozen by pyinstaller instead of a system one?
So, I found the solution:
Instead of calling the script with the 'os' module I imported the needed scripts :
from xscript import x
And called it directly via button:
tk.Button(mainframe, width=25, text="Something", command=x, bg='light grey')\
.grid(column=1, row=1, sticky=W)
2 caveats:
A file name init.py is needed in the same directory; same for the scripts imported.
I have Python 3.6.3 and Spyder 3.2.4, both installed along with Pyqt5 yesterday on a computer with a new installation of Windows 10. I am having a problem running some previously written Pyqt5 code in Spyder. The below code shows a minimum code snippet that reproduces the problem.
The Spyder IPython console hangs indefinitely on running the code, and never opens the window. Ctrl-C does not stop execution, so I have to kill Spyder. If I try to run it line by line, I observe that "w.show()" executes but does nothing, while "app.exec()" is the line that hangs. In contrast, if I instead run it from the command line console, "w.show()" makes a nonfunctional window appear, while "app.exec()" makes the window functional. All of the non-pyqt code I have run in Spyder executes just fine.
I'd prefer to develop code in Spyder because running code from the command line often takes 30-60s to start (presumably from the imports.)
I could run the code in Spyder on my old (now broken) system, so clearly it is a problem with my installation or computer. But I am at a loss as to what. I have already tried disabling my virus software, updating all of the relevant packages with pip, resetting Spyder from the Anaconda prompt, and restarting the computer. Any other ideas?
import sys
from PyQt5.QtWidgets import QApplication, QWidget
if not QApplication.instance():
app = QApplication(sys.argv)
else:
app = QApplication.instance()
print("app started")
w = QWidget()
w.resize(250, 250)
w.move(200, 200)
w.setWindowTitle('Test window')
print('app setting')
w.show()
print("shown")
app.exec_()
#sys.exit(app.exec_())
print("exit")
When running this in python it needs to be modified as below. I've modified your script a little to be able to let it run for you some of the main PyQt conventions. See also my inline comments to make sense of what you're trying to accomplish with your print lines. Enjoy!
# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication, QWidget
class MyMainUI(QtWidgets.QMainWindow):
def __init__(self, parent=None):
print ' Start Main'
super(MyMainUI, self).__init__(parent)
self.setWindowTitle('Test window')
self.resize(250, 250)
self.move(200, 200)
MySpidercodeHook()
def MySpiderCodeHook(self):
...link/run code...
if __name__ == '__main__':
app = QApplication(sys.argv) # no QApplication.instance() > returns -1 or error.
# Your setting up something that cannot yet be peeked
# into at this stage.
print("app started")
w = MyMainUI() # address your main GUI application
# not solely a widgetname..that is confusing...
x = 200
y = 200
# w.move(x, y) # normally this setting is done within the mainUI.
# See also PyQT conventions.
print 'app setting: moving window to position : %s' % ([x, y])
w.show()
print("shown")
app.exec_()
#sys.exit(app.exec_()) # if active then print "exit" is not shown..
# now is while using app.exec_()
#sys.exit(-1) # will returns you '-1' value as handle. Can be any integer.
print("exit")
sys.stdout.flush() # line used to print "printing text" when you're in an IDE
# like Komodo EDIT.
When I run the following script inside Spyder IDE, watchdog fires two FileModifiedEvent, instead of one, whenever a file inside the monitored folder is modified. It doesn't matter if the script is run through iPython or inside a regular console. The problem doesn't occur when the script is executed from a command prompt, thus the problem must be related to Spyder.
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
monitored_folder = 'D:\\Users\\myuser\\Desktop\\test'
class FolderMonitor(FileSystemEventHandler):
def on_any_event(self, event):
print(event)
observer = Observer()
observer.schedule(FolderMonitor(), monitored_folder)
observer.start()
try:
while True:
import time
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
Inside spyder, the output is:
<FileModifiedEvent: src_path='D:\\Users\\myuser\\Desktop\\test\\test.txt'>
<FileModifiedEvent: src_path='D:\\Users\\myuser\\Desktop\\test\\test.txt'>
Through a command prompt, the output is:
<FileModifiedEvent: src_path='D:\\Users\\camposb\\Desktop\\test\\test.txt'>
The code is being executed in Windows 7 with Python 3.5.1 and Spyder 2.3.8.
I have written a chess program in Python 3.4.3 and I am running the Python 3 interpreter in the interactive mode as follows:
python3 -i chess.py
However, the code after the class definitions get invoked twice and I do not know why. My code is on pastebin
You should remove the line from chess import * that is at the end of the file, it should not be needed.
Also, it is common to make sure that some of the code is not executed unless the code in the module is executed as a script.
if __name__ == '__main__':
# Not executed if the module is imported
g = Game()