Service fails to start when external log config file is involved - python

I am using PyInstaller to bundle my multi-module Python app into a one-file exe. The entry point for this app is a module extending win32serviceutil.ServiceFramework -- so this is meant to run as a Windows service. Problem arises when I try to furnish a user configurable logger ini file with this app. In my main module, I set up the logger thus,
log_file_path = path.join(path.dirname(path.abspath(__file__)), 'logging.conf')
logging.config.fileConfig(log_file_path)
My PyInstaller command is the following:
pyinstaller -F <main-file>.py -n <exe-name> --hidden-import=win32timezone --add-data "logging.conf;."
Once packaged, I install the produced exe as a service and it successfully registers as a Windows service. However when I attempt to start it, it fails.
The interesting bit is that an empty log file is created in my configured location. So this implies that 1) The application did read my config file, and 2) There's no permissions issue here. Has anyone tried to set up something like this that could help shed light on what I might be missing?

When using the one-file option with PyInstaller, we cannot validly use the __file__ variable in our code to identify the bundled app or its location. Instead, PyInstaller sets special system variables at runtime, like sys._MEIPASS and sys.executable; which specify the temporary folder created by the bootloader to run the app, and location of the frozen executable (the bootloader), respectively.
Once I changed my path manipulation to use these variables to locate the log config file, the file is successfully read and the service works.

Related

How to remove Bad magic number error in Pyinstaller

I have a python project which contains app.py and source.py files. Project also has other files for configs and logs. I have converted app.py to app.exe using pyinstaller
pyinstaller app.py
This has created a dist directory. I have copy pasted source.py, configs and the log files in the dist directory.
I also want to create a setup for this which will be installed on another machine. I cannot share the source.py file as it is thus instead of .py I have used source.pyc. I have now used inno compiler and have created a setup file.
As per my understanding, pyinstaller automatically binds the python interpreter so we do not need to install python on any other machine. I simply installed the exe and it started working fine.
In my project, I have a functionality which calls the source.pyc file like below:
exec(os.system("source.pyc install"))
This was working fine on my development machine but in other machine, it is giving me bad magic error.
As per online forums, this normally happens when we try to run the pyc file with different python version interpreter but in my case I am using the same pyinstaller interpreter. Then how come this error is coming.
Is there any other of compiling the additional files apart from app.py using pyinstaller. How can I remove this error. Thanks
PyInstaller does not bundle or bind a Python interpreter with the EXE file. The EXE file is a compiled binary file which, as it is compiled, does not need an interpreter. A PYC file still requires an interpreter.
You can compile the other files (i.e. source.py) using PyInstaller as well, and then move the compiled EXE file to the same directory as app.exe. In that case you would be able to run your command of import os; os.system("source.exe") from the main program. If your other compiled scripts require modules/libraries not used/included in the app.exe compilation, then when moving the compiled source.exe, you will need to move the bundled libraries to the app.exe directory as well.

Adding Module Mapping in IIS 8 to run python 3.6.3 web services asks for .exe or .dll extensions

I am trying to run my python(3) web service using IIS 8 following the instruction provided here
Everything is fine to the point where I try to add "FastCgi Module" in "Add Module Mapping" section. The problem is when I click on OK on "Add Module Mapping" window, the error pops up:
The specified executable for the handler must be .dll or .exe file. If the path to the script processor (only in the case of a .exe file) has spaces, use " marks to specify the executable.
I suppose there has to be a FastCgi.dll?
Is there a better way to achieve that?
P.S: I have read an ample of instructions regarding running python 2.6 web services on IIS using ISAPI_WSGI Handler and there are warnings regarding using it on later python versions, I wonder if that instructions hold up using python 3.3.6.
When you add Executable setting, it must be an executable, this means that is has to be either .exe or .dll. If you look at the picture in the instructions, you will see an executable there (python.exe).
If you don't provide path to an executable, error that specified executable must be .dll or .exe will pop up. Make sure you are referring to an executable there and it should be fine then.

Build app in macosx from python that must run in terminal

I'm trying to make a standalone, double click macosx app from a python module that has the
if __name__ == __main__
line in it to run. However, whenever I try to bundle it with something like py2app or pyinstaller, if I make an app bundle, a terminal window doesn't launch to run the program. Any idea on how to get around this? The terminal window needs to open in order to accept some user input. Let me know if more info is needed, this is the first time I've ever tried doing this.
P.S. I was able to get this to work for windows and package it within an installer for distribution.
Ok, I figured it out. Since building an app bundle from scratch is a bit tricky on a mac, it's better to find a program that will build it for you, I used applescript to accomplish this.
First, you need to build your executable file which is coming from the python code. I used pyinstaller with the --onefile option. so to build your executable use the command:
$pyinstaller --onefile yourPythonProgramYouWantToBuild.py
Once that's built, double click the file or open it with terminal to check that it works, all required code from various libraries have been included etc. If that works, onto the next step.
Open up applescript and set up a new script.
Here's how I got the thing to work
1) the applescript get's the directory its in
2) the compiled executable is going to be (manually) placed in the app bundle and the script inside the app is going to know where it is in the app bundle
3) the script finds the exact path to the executable, and tells the Terminal application to run it
Ok so how to do that?
Make a new applescript, and just put some dummy code in it, for example :
display dialog "Hello, world!"
Next, save this applescript as a app bundle. Go into the fresh app bundle you just made and navigate within the app's package contents Contents->Resources->Scripts->main.scpt. Now open up the main.scpt file and begin to edit it.
In your main.scpt, first find the directory where the applescript is
tell application "Finder"
set current_path to container of (path to me) as string
end tell
However if you throw in a display dialog current_path in the apple script, when you run that from the app bundle, you'll find that it won't take you all the way inside the app bundle. For example, if you were running the app from the desktop the path you would get would be something like ~/Desktop/, which is not what we want, because we need to get the path inside the app. So next we need to append some stuff to the end of that in order to get to the good stuff inside the app bundle. Use a command similar to this:
set current_path to current_path & "TheNameOfThe.app" & ":" & "theNameOfYourCompiledExecutable"
Now we have a path to an executable that (might be) in your app's bundle. Now, make a POSIX path and tell terminal to run a the script.
set a to POSIX path of current_path
tell application "Terminal"
do script a
end tell
The last thing to do is to open up the app package contents and copy your onefile executable to the correct place within the app bundle. Change the app icon as necessary.

Embedding an executable within a py2app application

I have a python script that I want to package as a Mac application bundle with py2app. That script calls a CLI executable.
How do I embed that executable in the application bundle?
I tried to edit setup.py in order to include it as a Resource but in that case, execution privileges are lost. Moreover the strip stage of py2app raises an error. I wonder if there is a specific setup.py option that could copy the executable in Content/MacOS instead of Content/Resources.
Adding the CLI executable to the resources it the correct way to do it, but that doesn't work due to a bug in py2app (the file permissions aren't copied at the moment).
The easiest workaround is to reset the file permissions after calling py2app.

Managing Python Path When Moving Code from Development Computer to Target

I have a python project with this directory structure and these files:
/home/project_root
|---__init__.py
|---setup
|---__init__.py
|---configs.py
|---test_code
|---__init__.py
|---tester.py
The tester script imports from setup/configs.py with the reference "setup.configs". It runs fine on my development machine.
This works on the development (Linux) computer. When I move this to another (Linux) computer, I set the PYTHONPATH with
PYTHONPATH = "/home/project_root"
But when I run tester.py, it can't find the configs module. And when I run the interactive Python interpreter, sys.path doesn't include the /home/project_root directory. But /home/project_root does appear when I echo $PYTHPATH.
What am I doing wrong here?
(I don't want to rely on the .bashrc file to set the PYTHONPATH for the target machine -- the code is for a Django application, and will eventually be run by www-data. And, I know that the apache configuration for Django includes a specification of the PYTHONPATH, but I don't want to use that here as I'm first trying to make sure the code passes its unit tests in the target machine environment.)
CURIOUSER AND CURIOUSER
This seems to be a userid and permissions problem.
- When launched by a command from an ordinary user, the interpreter can import modules as expected.
- When launched by sudo (I'm running Ubuntu here), the interpreter cannot import modules as expected.
- I've been calling the test script with sudo, as the files are owned by www-data (b/c they'll be called by the user running apache as part of the Django application).
- After changing the files' ownership to that of an ordinary user, the test script does run without import errors (albeit, into all sorts of userid related walls).
Sorry to waste your time. This question should be closed.
Stick this in the tester script right before the import setup.configs
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), os.path.pardir))
sys.path is a list of all the directories the python interpreter looks for when importing a python module.
This will add the parent directory which contains setup module to the beginning of that list which means that the local directory will be checked first. That is important if you have your module installed system wide. More info on that here: sys doc.
EDIT: You could also put a .pth file in /usr/local/lib/python2.X/site-packages/ A .pth file is simply a text file with a directory path on each line that the python interpreter will search in. So just add a file with this line in it:
/home/project_root
Try explicitly setting your python path in your scripts. If you don't want to have to change it, you could always add something like "../" to the path in tester. That is to say:
sys.path.append("../")
(I don't want to rely on the .bashrc file to set the PYTHONPATH for the target machine -- the code is for a Django application, and will eventually be run by www-data. And, I know that the apache configuration for Django includes a specification of the PYTHONPATH, but I don't want to use that here as I'm first trying to make sure the code passes its unit tests in the target machine environment.)
If the code is for a Django application, is there a reason you're not testing it in the context of a Django project? Testing it in the context of a Django project gives a couple benefits:
Django's manage.py will set up your Python environment for you. It'll add the appropriate project paths to sys.path, and it'll set the environment variable DJANGO_SETTINGS_MODULE correctly.
Django's libraries include ample unit testing facilities, and you can easily extend that functionality to include your own testing facilities. Executing tests in a Django project is as easy as executing a single command via manage.py.

Categories

Resources