subprocess cannot run python executable in non-interactive mode? - python

I am using python 3.6.3 and subprocess module to run another python script
# main.py
#!/bin/env python
from subprocess import Popen,PIPE
from sys import executable
p = Popen([executable, 'test.py', 'arg1'],shell=True, stdout=PIPE)
p.wait()
print(p.stdout.read().decode())
and
# test.py
import sys
print(sys.argv)
I expect it will run and execute test.py. However, it opens an python interpreter in interactive mode!
I tested shell=False option, it works. I tested string form rather than list form of args, it works.
I am not sure if it is a bug or not.

You need to remove shell=True or change the first argument to be executable + ' test.py arg1' instead of [executable, 'test.py', 'arg1'].
As explained in the documentation, with shell = True, it will run it as /bin/sh -c python test.py arg1, which means python will be run without arguments.

Related

Linux, Python open terminal run global python command

Not sure if this is possible. I have a set of python scripts and have modified the linux PATH in ~/.bashrc so that whenever I open a terminal, the python scripts are available to run as a command.
export PATH=$PATH:/home/user/pythonlib/
my_command.py resides in the above path.
I can run my_command.py (args) from anywhere in terminal and it will run the python scripts.
I'd like to control this functionality from a different python script as this will be the quickest solution to automating my processing routines. So I need it to open a terminal and run my_command.py (args) from within the python script I'm working on.
I have tried subprocess:
import subprocess
test = subprocess.Popen(["my_command.py"], stdout=subprocess.PIPE)
output = test.communicate()[0]
While my_command.py is typically available in any terminal I launch, here I have no access to it, returns file not found.
I can start a new terminal using os then type in my_command.py, and it works
os.system("x-terminal-emulator -e /bin/bash")
So, is there a way to get the second method to accept a script you want to run from python with args?
Ubuntu 16
Thanks :)
Popen does not load the system PATH for the session you create in a python script. You have to modify the PATH in the session to include the directory to your project like so:
someterminalcommand = "my_command.py (args)"
my_env = os.environ.copy()
my_env["PATH"] = "/home/usr/mypythonlib/:" + my_env["PATH"]
combine = subprocess.Popen(shlex.split(someterminalcommand), env=my_env)
combine.wait()
This allows me to run my "my_command.py" file from a different python session just like I had a terminal window open.
If you're using Gnome, the gnome-terminal command is rather useful in this situation.
As an example of very basic usage, the following code will spawn a terminal, and run a Python REPL in it:
import subprocess
subprocess.Popen(["gnome-terminal", "-e", "python"])
Now, if you want to run a specific script, you will need to concatenate its path with python, for the last element of that list it the line that will be executed in the new terminal.
For instance:
subprocess.Popen(["gnome-terminal", "-e", "python my_script.py"])
If your script is executable, you can omit python:
subprocess.Popen(["gnome-terminal", "-e", "my_script.py"])
If you want to pass parameters to your script, simply add them to the python command:
subprocess.Popen(["gnome-terminal", "-e", "python my_script.py var1 var2"])
Note that if you want to run your script with a particular version of Python, you should specify it, by explicitly calling "python2" or "python3".
A small example:
# my_script.py
import sys
print(sys.argv)
input()
# main.py
import subprocess
subprocess.Popen(["gnome-terminal", "-e", "python3 my_script.py hello world"])
Running python3 main.py will spawn a new terminal, with ['my_script.py', 'hello', 'world'] printed, and waited for an input.

can't execute the blender python through subprocess

My blender is at the path of '/home/abc/Destkop/blender/blender-2.78'. When command line is at the path '/home/abc/Destkop/blender/blender-2.78', executing './blender -b /home/abc/Destkop/blender/car.model' through command line is working.
I am trying to execute blender in python through subprocess, but the code doesn't work with an error "/usr/bin/python: can't open file ./blender -b /home/abc/Destkop/blender/car.model", but the path is all right
here is my code
import os
import sys
import subprocess
if __name__="__main__":
os.chdir("/home/abc/Destkop/blender/blender-2.78")
subprocess.Popen([sys.executable],"./blender -b /home/abc/Destkop/blender/car.m
Try this:
subprocess.check_call(["./blender", "-b", "/home/abc/Destkop/blender/car.m"])
Note that the shell arg defaults to False, which means the args must be a sequence (list or tuple) of words making up the command-line, not a single command-line string.

how to run python script from the console as if called from command prompt?

The python script I would use (source code here) would parse some arguments when called from the command line. However, I have no access to the Windows command prompt (cmd.exe) in my environment. Can I call the same script from within a Python console? I would rather not rewrite the script itself.
%run is a magic in IPython that runs a named file inside IPython as a program almost exactly like running that file from the shell. Quoting from %run? referring to %run file args:
This is similar to running at a system prompt python file args,
but with the advantage of giving you IPython's tracebacks, and of
loading all variables into your interactive namespace for further use
(unless -p is used, see below). (end quote)
The only downside is that the file to be run must be in the current working directory or somewhere along the PYTHONPATH. %run won't search $PATH.
%run takes several options which you can learn about from %run?. For instance: -p to run under the profiler.
If you can make system calls, you can use:
import os
os.system("importer.py arguments_go_here")
You want to spawn a new subprocess.
There's a module for that: subprocess
Examples:
Basic:
import sys
from subprocess import Popen
p = Popen(sys.executable, "C:\test.py")
Getting the subprocess's output:
import sys
from subprocess import Popen, PIPE
p = Popen(sys.executable, "C:\test.py", stdout=PIPE)
stdout = p.stdout
print stdout.read()
See the subprocess API Documentation for more details.

Python sh import causing Unresolved Import error in PyDev

I'm using sh in python 2.7.5 to call shell programs like curl and mkdir, but in PyDev plugin 2.7.5 under Eclipse 4.3.0. the following line gives an Unresolved Import error:
from sh import curl, printenv, mkdir, cat
I'm able to run the above code in a python shell. I do have the path to sh included in the Libraries pane in the Interpreter - Python window in Preferences, so I don't think that's the problem.
Try using the subprocess module to call console commands. For example:
from subprocess import call
dir_name = '/foo/bar/'
call('mkdir %s'%dir_name, shell=True)
Like Bill said, subprocess is a good choice here. I'd personally recommend using the Popen because it doesn't block, and allows you to wait for commands to finish with its communicate() method, which also returns stdout and stderr. Also, avoid using shell=True when possible. Usage:
import subprocess
testSubprocess = subprocess.Popen(['mkdir', dir_name], stdout=subprocess.PIPE)
testOut, testErr = testSubprocess.communicate()

Python/CMD command

So I am running a command in my python py file
myNewShell = os.system('start "%s" /d "%s" cmd /f:on /t:0A /k "W:\\Desktop\\alias.bat"' % (myShot, myWorkDir))
This opens up a shell
How exactly would I input something into this shell directly from my python script, thus bypassing your actual cmd.exe. I have a bunch of DOSKEYs set up, such as maya which opens up the maya program. How would I add a line of code to my python script, so that it loads the shell with those aliases and inputs my command directly
Take a look at the powerful and useful subprocess module
You can then do code like this
import subprocess
pro = subprocess.Popen("cmd", stdout=subprocess.PIPE, stdin=subprocess.PIPE)
pro.stdin.write("mybat.bat\n")
pro.stdin.write("myother.bat\n")
pro.stdin.write("start mysillyprogram\n")
pro.stdin.flush()
pro.terminate() # kill the parent

Categories