I am using py2app to bundle a python script, that uses the anaconda python distribution.
Since py2app doesn't play well with terminal scripts that need user input, I have a Tkinter file that py2app's setup.py launches, which then further launches my .py script using popen.
Locally, this works fine:
import subprocess as sub
command = "~/anaconda/bin/python -u myscript.py " + str(groups_count)
process = sub.Popen(command, shell=True, stdout=sub.PIPE, stderr=sub.PIPE, bufsize=1, universal_newlines=True)
But when I want to distribute this, I need to replace hardcoded paths and run this using the distribution contained within
import subprocess as sub
command = sys.executable + " -u myscript.py " + str(groups_count)
process = sub.Popen(command, shell=True, stdout=sub.PIPE, stderr=sub.PIPE, bufsize=1, universal_newlines=True)
This results in an error:
/bin/sh: /Users/username/projectname/appname/dist/MyOSXapp.app/Contents/MacOS/python: Permission denied
If I look at libpython2.7.dylib within /MyOSXapp.app/Contents/Frameworks it doesn't seem to be executable, but is readable by everyone. This is all assembled by py2app.
I need to run popen on my anaconda python distributed within pyapp. How do I do this?
I worked around this by adding executable permission to the python file saved by py2app within the osx .app file.
$ chmod +x ./dist/MyOSXapp.app/Contents/MacOS/python
Additionally, a fix for this was also added in py2app via issue 228.
Related
Using Windows, I have a python program that runs CMD within using subprocess.Popen. When I run it from python, it works. When I create the executable and run it, it doesn't find the tool I am using (esptool):
'esptool' is not recognized as an internal or external command,
operable program or batch file.
The command call I have built so far with --add-binary is as follows:
pyinstaller -F main.py -n "ProgramTest" -i resources/ico/icon.ico --add-binary "C:\\Users\\<my_user>\\AppData\\Local\\miniconda3\\envs\\this_env\\Scripts\\esptool.exe;."
(I have obtained the path to esptool by running where.exe esptool. That's the only instance of esptool that appears.)
Also tried the solution listed here, where they use = after the flag (--add-binary="...") and using lib as in --add-binary="...;lib".
Perhaps it has something to do with my python environments? Maybe I am not adding correctly the executable?
The code to execute my cmd lines is as follows:
import subprocess
def execute(cmd):
popen = subprocess.Popen(
cmd, shell=True, stdout=subprocess.PIPE, universal_newlines=True
)
for stdout_line in iter(popen.stdout.readline, ""):
yield stdout_line
popen.stdout.close()
return popen.wait()
My environment:
OS Name: Microsoft Windows 10 Pro
Version: Windows 10.0.19045 Build 19045
miniconda: 23.1.0
Python (env): 3.10.9
PyInstaller: 5.8.0
esptool: 3.1
Same problem as adding data, you must create a relative path to the .exe.
To be able to run the command in both an .exe and as a python script, I used:
def get_exe_path(exe_name):
if getattr(sys, "frozen", False):
application_path = os.path.join(sys._MEIPASS, exe_name + ".exe")
else:
application_path = exe_name
return application_path
Now, just by appending it at the beggining of the call I want to call, it works:
ESPTOOL_PATH = get_exe_path("esptool")
order = ESPTOOL_PATH + " --port " + port + " --chip esp32 erase_flash"
I have this python file in the same folder as the one being executed. And I'm trying to execute the file in a new terminal window (I'm using Linux) using subprocess. The new window opens, but its giving me the error Failed to execute child process "/usr/bin/python3 /media/root/MYDRIVE/tools/sniff/sniffer.py" (No such file or directory). Could anyone explain?
import subprocess
current_path = os.path.dirname(os.path.realpath(__file__))
subprocess.call(['gnome-terminal', '-x', '/usr/bin/python3 '+ current_path+'/sniffer.py'])
Try the following
import os
os.system("gnome-terminal -e 'bash -c \"python3 sniffer.py\"'")
I'm trying to write a script that opens a new terminal then runs a separate python script from that terminal.
I've tried:
os.system("gnome-terminal 'python f.py'")
and
p = Popen("/usr/bin/gnome-terminal", stdin=PIPE)
p.communicate("python f.py")
but both methods only open a new terminal and do not run f.py. How would I go about opening the terminal AND running a separate script?
Edit:
I would like to open a new terminal window because f.py is a simply server that is running serve_forever(). I'd like the original terminal window to stay "free" to run other commands.
Like most terminals, gnome terminal needs options to execute commands:
gnome-terminal [-e, --command=STRING] [-x, --execute]
You probably need to add -x option:
x, --execute
Execute the remainder of the command line inside the terminal.
so:
os.system("gnome-terminal -x python f.py")
That would not run your process in the background unless you add & to your command line BTW.
The communicate attempt would need a newline for your input but should work too, but complex processes like terminals don't "like" being redirected. It seems like using an interactive tool backwards.
And again, that would block until termination. What could work would be to use p.stdin.write("python f.py\n") to give control to the python script. But in that case it's unlikely to work.
So it seems that you don't even need python do to what you want. You just need to run
python f.py &
in a shell.
As of GNOME Terminal 3.24.2 Using VTE version 0.48.4 +GNUTLS -PCRE2
Option “-x” is deprecated and might be removed in a later version of gnome-terminal.
Use “-- ” to terminate the options and put the command line to execute after it.
Thus the preferred syntax appears to be
gnome-terminal -- echo hello
rather than
gnome-terminal -x echo hello
Here is a complete example of how you would call a executable python file with subprocess.call Using argparse to properly parse the input.
the target process will print your given input.
Your python file to be called:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--file", help="Just A test", dest='myfile')
args = parser.parse_args()
print args.myfile
Your calling python file:
from subprocess import call
#call(["python","/users/dev/python/sandboxArgParse.py", "--file", "abcd.txt"])
call(["gnome-terminal", "-e", "python /users/dev/python/sandboxArgParse.py --file abcd.txt"])
Just for information:
You probably don't need python calling another python script to run a terminal window with a process, but could do as follows:
gnome-terminal -e "python /yourfile.py -f yourTestfile.txt"
The following code will open a new terminal and execute the process:
process = subprocess.Popen(
"sudo gnome-terminal -x python f.py",
stdout=subprocess.PIPE,
stderr=None,
shell=True
)
I am running a uWS server with this.In my case Popen didn't help(Even though it run the executable, still it couldn't communicate with a client -: socket connection is broken).This is working.Also now they recommends to use "--" instead of "-e".
subprocess.call(['gnome-terminal', "--", "python3", "server_deployment.py"])
#server_deployment.py
def run():
execution_cmd = "./my_executable arg1 arg2 dll_1 dll_2"
os.system(execution_cmd)
run()
consider portion of Python code(Python 2.7) on Win 7 machine,
toolPath="C:\\Program Files (x86)\\Target Compiler Technologies\\adsp2-12R2\\bin\\WINbin"
This is executed from python script under
C:\dev\bin\toplevel\python
Now, I need to execute a command that runs(compiles and builds a DSP library, .prx is a project file for the library)
as
C:\Program Files (x86)\Target Compiler
Technologies\adsp2-12R2\bin\WINbin\chessmk.exe
".\..\..\..\dev\lib\adsp2\mylibs.prx -r -s
I am able to do that in cmd.exe shell as
%toolPath%\chessmk.exe "..\..\..\dev\lib\adsp2\mylibs.prx" -r -s
I can do the same in Python as
cmd = '"C:\\Program Files (x86)\\Target Compiler Technologies\\adsp2-12R2\\bin\\WINbin\\chessmk.exe" "C:\\SVN\\ASROmni\\trunk1\\\dev\\lib\\adsp2\\mylibs.prx" -r'
subprocess.check_output(cmd,stderr=subprocess.STDOUT,shell=False)
But, I have not been able to write similar code for Python, with relative paths and using toolpath variable.
for example,
cmd = 'toolPath+"\\chessmk.exe" ".\\..\\..\\..\\dev\\lib\\adsp2\\mylibs.prx" -r -s'
subprocess.check_output(cmd,stderr=subprocess.STDOUT,shell=False)
gives error:
WindowsError: [Error 2] The system cannot find the file specified
following did not work too:
cmd = '"C:\\Program Files (x86)\\Target Compiler Technologies\\adsp2-12R2\\bin\\WINbin\\chessmk.exe" ".\\..\\..\\..\\dev\\lib\\adsp2\\mylibs.prx" -r'
subprocess.check_output(cmd,stderr=subprocess.STDOUT,shell=False)
Update:
from one of the comments, I tried
cmd = os.path.join(toolPath,"chessmk.exe")+' C:\\SVN\\ASROmni\\trunk1\\\dev\\lib\\adsp2\\mylibs.prx -r'
it works,but the relative path one
cmd = os.path.join(toolPath,"chessmk.exe")+' .\\..\\..\\..\\dev\\lib\\adsp2\\mylibs.prx -r'
still dosn't.
any help.( This is my first day with python, so bear with me)
please note that the cmd should be run from within Python, not invoking shell=True.
Thanks
sedy
It may be how you're passing the arguments to check_output(), try this instead:
toolPath = ('"C:\\Program Files (x86)\\Target Compiler Technologies\\'
'adsp2-12R2\\bin\\WINbin\\chessmk.exe"')
cmd = [toolPath, '"..\..\..\dev\lib\adsp2\mylibs.prx"', '-r' '-s']
subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=False)
However the relative path for the location of mylibs.prx may still be a problem. You might be able to make it work by calling os.chdir() right before calling check_output().
I need to execute this script from my Python script.
Is it possible? The script generate some outputs with some files being written. How do I access these files? I have tried with subprocess call function but without success.
fx#fx-ubuntu:~/Documents/projects/foo$ bin/bar -c somefile.xml -d text.txt -r aString -f anotherString >output
The application "bar" also references to some libraries, it also create the file "bar.xml" besides the output. How do I get access to these files? Just by using open()?
Thank you,
Edit:
The error from Python runtime is only this line.
$ python foo.py
bin/bar: bin/bar: cannot execute binary file
For executing the external program, do this:
import subprocess
args = ("bin/bar", "-c", "somefile.xml", "-d", "text.txt", "-r", "aString", "-f", "anotherString")
#Or just:
#args = "bin/bar -c somefile.xml -d text.txt -r aString -f anotherString".split()
popen = subprocess.Popen(args, stdout=subprocess.PIPE)
popen.wait()
output = popen.stdout.read()
print output
And yes, assuming your bin/bar program wrote some other assorted files to disk, you can open them as normal with open("path/to/output/file.txt"). Note that you don't need to rely on a subshell to redirect the output to a file on disk named "output" if you don't want to. I'm showing here how to directly read the output into your python program without going to disk in between.
The simplest way is:
import os
cmd = 'bin/bar --option --otheroption'
os.system(cmd) # returns the exit status
You access the files in the usual way, by using open().
If you need to do more complicated subprocess management then the subprocess module is the way to go.
For executing a unix executable file. I did the following in my Mac OSX and it worked for me:
import os
cmd = './darknet classifier predict data/baby.jpg'
so = os.popen(cmd).read()
print so
Here print so outputs the result.