Python - Two processes after compiling? - python

I'm currently working on a small python script, for controlling my home PC (really just a hobby project - nothing serious).
Inside the script, there is two threads running at the same time using thread (might start using threading instead) like this:
thread.start_new_thread( Function, (Args) )
Its works as intended when testing the script... but after compiling the code using Pyinstaller there are two processes (One for each thread - I think).
How do I fix this?

Just kill the loader from the main program if it really bothers you. Here's one way to do it.
import os
import win32com.client
proc_name = 'MyProgram.exe'
my_pid = os.getpid()
wmi = win32com.client.GetObject('winmgmts:')
all_procs = wmi.InstancesOf('Win32_Process')
for proc in all_procs:
if proc.Properties_("Name").Value == proc_name:
proc_pid = proc.Properties_("ProcessID").Value
if proc_pid != my_pid:
print "killed my loader %s\n" % (proc_pid)
os.kill(proc_pid, 9)

Python code does not need to be "compiled with pyinstaller"
Products like "Pyinstaller" or "py2exe" are usefull to create a single executable file that you can distribute to third parties, or relocate inside your computer without worrying about the Python instalation - however, they don add "speed" nor is the resulting binary file any more "finished" than your original .py (or .pyw on Windows) file.
What these products do is to create another copy of the Python itnrepreter, alogn with all the modules your porgram use, and pack them inside a single file. It is likely the Pyinstaller keep a second process running to check things on the main script (like launching it, maybe there are options on it to keep the script running and so on). This is not part of a standard Python program.
It is not likely Pyinstaller splits the threads into 2 separate proccess as that would cause compatibility problems - thread run on the same process and can transparently access the same data structures.
How a "canonical" Python program runs: the main process, seen by the O.S. is the Python binary (Python.exe on Windows) - it finds the Python script it was called for - if there is a ".pyc" file for it, that is loaded - else, it loads your ".py" file and compiles that to Python byte code (not to windwos executable). This compilation is authomatic and transparent to people running the program. It is analogous to a Java compile from a .java file to a .class - but there is no explicit step needed by the programmer or user - it is made in place - and other factors control wether Python will store the resulting bytecode as .pyc file or not.
To sum up: there is no performance impact in running the ".py" script directly instead of generating an .exe file with Pyinstaller or other product. You have a disk-space usage inpact if you do, though, as you will have one copy of the Python interpreter and libraries for each of your scripts.
The URL pointeded by Janne Karila on the comment nails it - its even worse than I thought:
in order to run yioru script, pyinstaller unpacks Python DLLs and modules in a temporary directory. The time and system resources needed todo that, compared with a single script run is non-trivial.
http://www.pyinstaller.org/export/v2.0/project/doc/Manual.html?format=raw#how-one-file-mode-works

Related

Password protect a Python Script that is Scheduled to run daily

I have a python script that is scheduled to run at a fixed time daily
If I am not around my colleague will be able to access my computer to run the script if there is any error with the windows task scheduler
I like to allow him to run my windows task scheduler but also to protect my source code in the script... is there any good way to do this, please?
(I have read methods to use C code to hide it but I am only familiar with Python)
Thank you
Compile the source to the .pyc bytecode, and then move the source somewhere inaccessible.
Open a terminal window in the directory containing your script
Run python -m py-compile <yourfile.py> (you should get a yourfile.pyc file)
Move <yourfile.py> somewhere secure
your script can now be run as python <yourfile.pyc>
Note that is is not necessarily secure as such - there are ways to decompile the bytecode - but it does obfuscate it, if that is your requirement.

Batch Rendering file from a python script without openeing Maya

I have one Maya scene and a Python script where import obj files into it. I need to create a batch render file which calls the maya file and applies the script without opneing maya.
I have this code in a .sh file:
#!/bin/bash
"/Applications/Autodesk/maya2016/Maya.app/Contents/bin/Render" -r file -s 1 -e 4 -cam camera1 -rd "/Users/MyComp/Documents/maya/projects/default/images" "/Users/MyComp/Documents/maya/projects/default/Scenes/test1.mb"
But I have this code into the script which can be an issue or maybe not:
def renderFile(i):
cmds.setAttr("defaultRenderGlobals.imageFilePrefix", i, type="string")
cmds.render(batch=True)
If I execute this .sh file it renders without the python script. How can I add the python script?
I need that file for a renderfarm purposes
I know it's an old thread but thought I'd jump in just incase someone finds this thread in a search.
The comments seem a little confused. This comes from the fact that there are two different Python interpreters being talked about. The first is the system level one, which the original question seems to be talking about. In that case, you can use any of the various shell command launchers (like, subprocess/Popen) that suit your need. Here you are looking to run the render command like you would any other command in in the shell.
In the responses, people there are referring to the other interpreter, the custom Maya Python interpreter (mayapy.exe). In that case you are working with actual Maya libraries and it's the same as working with Python in it's shell, with the added Maya libraries/environment.
The two have different uses, the first is to control things like they were in the shell and the second is controlling things inside of a Maya context. Hope that clarifies things.

Does converting an interpreted script to an executable increase speed?

In general I'm curious, does using a utility that converts a non-exe to an exe increase speed? It's my understanding that they just package the interpreter inside the exe.
In specific, if you have a python script and use py2exe on it, does the resulting executable run faster than the .py? My boss seems to have the assumption it does but I'm not so sure.
Especially when dealing with multiple modules. For example say you have modules first.py and second.py. You compile them all to executables. When they were .py they second.py could be called as
from second import main
main()
Now that they're executables you have to start a new process, which surely is slower?
subproccess.call(["second.exe"], shell=True)
Do I understand this correctly? Or does importing from another python module actually start a new instance of the python interpreter or something?
In our case the target platform is always Windows.
Your boss is misinformed. All py2exe does is package your program into a self-contained package capable of running without dependencies. It is still the same bytecode running on the same interpreter (well, whatever one is packaged).
See this other answer for about all of the "optimization" you can get out of using -o flags.
Also, yes, definitely run some benchmarks to confirm for yourself.

Calling to a Sikuli script from Python (Selenium)

While running Selenium tests on a website, I have some Flash elements that I cannot test with Selenium/Python. I wanted to call out for a separate terminal window, run the Sikuli OCR tests, and then back into the Selenium/Python testing. I've not been able to figure this out exactly. I put XXX where I do not know the arguments for a new Terminal to open and run the Sikuli script.
def test_05(self):
driver = self.driver
driver.get(self.base_url + "/")
driver.find_element_by_link_text("Home").click()
driver.find_element_by_id("open_popup").click()
driver.find_element_by_id("screen_name").send_keys("user")
driver.find_element_by_id("password").send_keys("pwd")
driver.find_element_by_id("login_submit").click()
driver.find_element_by_id("button").click()
time.sleep(120)
os.system('XXX')
os.system('./Sikuli/sikuli-script -r test.sikuli')
I am sure there are a couple items wrong here. Any help would be greatly appreciated. I've searched and read what I can find on this already, but can't get it all to work together.
I ran into a similar issue, so I wrote a CPython module for Sikuli. The module is hosted on GitHub and available via pip install sikuli. It's able to access an included Sikuli jar using pyjnius, so you don't have to use Jython or even install Sikuli itself (although I'd recommend it for recording purposes). The module currently covers most of the simpler Sikuli functions, so it should cover a lot of use cases.
After installing, a simple from sikuli import * will get you started, but as a best practice, I'd suggest only importing the functions you want to use. This is particularly important for this module, because sikuli has a type function which overrides Python's own type function.
If your sikuli script is completely independent and you just want to run it for once and then have control back to your python script.
Then you can create a batch file, which calls your sikuli script and call this batch file from your python script instead.
Once the batch file is done running, it exits and returns the control back to your python script.
Sample Batch file:
#echo off
call C:\Sikuli\runIDE.cmd -r C:\Automation\Test1.sikuli
exit
Code snippet to call Sikuli script from inside python:
import subprocess
def runSikuliScript(path):
filepath = path
p = subprocess.Popen(filepath, shell=True, stdout = subprocess.PIPE)
stdout, stderr = p.communicate()
print "Done Running Sikuli"
p = "C:\\Automation\\Test1\\test1.bat"
runSikuliScript(p)
// You can carry on writing your python code from here on
For calling Sikuli code from Selenium, my first choice would be TestAutomationEngr's suggestion of using Java, since Selenium and Sikuli both have native Java bindings.
Since you want to use Python, you should try running Selenium under Jython. It's important to remember that Sikuli is Jython, which is probably why you're not able to import it. (The other reason would be that you don't have it in Jython's module path.) I have not tried this myself, but there was a bug fixed last year in Selenium which indicates that it should be fine under Jython.
Note that if you call your Sikuli code directly from Jython, you need to add
from sikuli.Sikuli import *
to the top. This is because the Sikuli IDE implicitly adds that to all Sikuli code.
Finally, your last resort is to call Sikuli from the command line. There's an FAQ for that. You probably want the "without IDE" version, where you're calling Java and passing in the sikuli-script JAR file.

Distributing python-written executable with veusz

I would like to distribute an application written in python as a .exe file. I have already been able to do this using py2exe, but now I have incorporated the veusz library into my code. Ideally my program should open up a veusz plot (as it does on my computer, which has python, numpy, etc. all installed). However, I want to distribute an executable that does this without having to install python.
When I try running my setup.py with py2exe, everything goes fine and the exe is built. However, once the application runs and gets to the point where it is to display the graph, it sends up:
Runtime error: Unable to find veusz executable on system path.
Can I fix this without having to install a bunch of stuff on my clients' computers? Is this possible? And if I must install something, what is the minimum amount of software I need to install?
Veusz runs its user interface in a separate python process so that it does not block python. If you look at veusz/embed.py, it tries to start up python or a veusz executable. You'd need to modify embed.py to start your .exe (sys.executable) if frozen instead of veusz and pass some special parameter which your program would interpret to start running veusz.embed_remote.runremote.
The python multiprocessing module has to do something similar - you need to call a multiprocess function which checks whether the program was starting by multiprocessing - to get around the fact that Windows doesn't have a working fork.

Categories