Python create shell for several processes - python

I have several command execution in python on Windows using subprocess.call(), but for each one I need to execute batch file with environmet setup before calling proper command, it looks like this
subprocess.call(precommand + command)
Is there way to "create" shell in python that will have batch file executed only once and in that shell command will be executed several times?

Write commands to a bat-file (tempfile.NamedTemporaryFile())
Run the bat-file (subprocess.check_call(bat_file.name))
(not tested):
#!/usr/bin/env python
from __future__ import print_function
import os
import subprocess
import tempfile
with tempfile.NamedTemporaryFile('w', suffix='.bat', delete=False) as bat_file:
print(precommand, file=bat_file)
print(command, file=bat_file)
rc = subprocess.call(bat_file.name)
os.remove(bat_file.name)
if rc != 0:
raise subprocess.CalledProcessError(rc, bat_file.name)

Do you need to get output from every command separately? If no - you can convey these commands using &&, || or ;
cd dir && cp test1 test2 && cd -

Related

How to source workspace in python script

I am using a python script in order to run four different python scripts that each execute a command, the purpose of this is to run the main python script on startup. This is what is inside the main python script:
#!/usr/bin/env/python
import os
os.system('x-terminal-emulator -e python ./one.py')
os.system('x-terminal-emulator -e python ./two.py')
os.system('x-terminal-emulator -e python ./three.py')
os.system('x-terminal-emulator -e python ./four.py')
When I run it, it does create four terminals and executes each of the .py in each terminal, but the one.py, two.py, and three.py return an error of "sh: 1: source: not found". I know this is because I am using these lines:
os.system('cd /home/nvidia/catkin_ws')
os.system('source devel/setup.bash')
Sourcing is needed in order the commands after it, how do I fix this problem? I am using ROS Kinetic with Linux Ubuntu 16.04.
Content of one.py
#!/bin/bash
import os
os.system('cd /home/nvidia/catkin_ws')
os.system('source devel/setup.bash')
os.system('roslaunch pocketsphinx continuous.launch spdict:=/home/nvidia/catkin_ws/src/pocketsphinx/demo/speaker_test.dic spkws:=/home/nvidia/catkin_ws/src/pocketsphinx/demo/speaker_test.kwlist sphmm:=/home/nvidia/catkin_ws/src/pocketsphinx/demo/speaker_verification/an4.ci_cont_adapt/ dict:=/home/nvidia/catkin_ws/src/pocketsphinx/demo/keywords_spk_verification.dic kws:=/home/nvidia/catkin_ws/src/pocketsphinx/demo/keywords_spk_verification.kwlist gram:=/home/nvidia/catkin_ws/src/pocketsphinx/demo/asr_spk grammar:=asr rule:=rule sp_verif:=false')
Content of two.py
#!/bin/bash
import os
os.system('cd /home/nvidia/catkin_ws')
os.system('source devel/setup.bash')
os.system('rosrun pocketsphinx execute_commands.py')
Content of three.py
#!/bin/bash
import os
os.system('cd ~/catkin_astra')
os.system('source devel/setup.bash')
os.system('roslaunch astra_launch astra.launch')
os.system() starts a new shell, executes whatever you pass it and then closes the shell down again. Subsequently created shells are not affected by any changes to that shell, like changing the working directory or sourcing stuff.

How to send multiple commands to terminal(linux) from python?

I want to send commands to run a python script to the Linux terminal. I have a list of python files which I want to run and I want to run them one after the other as we read the list sequentially. Once the first file is finished, it should send the second one to run and so on.
You can run scripts sequentially using the following command:
python script1.py && python script2.py && python script3.py
&& runs the next script only if the previous has run successfully.
You can iterate through using the subprocess module:
import subprocess
script_list = ['script1.py', 'script2.py']
for script in script_list:
args = ['python', script]
p = subprocess.check_call(args)
You can use the check_call function of the subprocess module which is a blocking call. when you iterate through the list one will run after another.
import subprocess
files = ['script1.py', 'script2.py']
for _file in files:
call_output = subprocess.check_all(['python', _file])

Run ElasticSearch using Python

I am trying to turn on ElasticSearch node using python. I am doing this by running a shell script via python. I have tried the below commands in python to run the shell script :
import os
cmd = 'cd C:\Users\anoop\desktop\kibi\elasticsearch 2.3.3\bin && .\elasticsearch'
os.system(cmd)
from subprocess import call
call('cd C:\Users\anoop\desktop\kibi\elasticsearch 2.3.3\bin && .\elasticsearch')
import subprocess
p = subprocess.Popen('C:\Users\anoop\Desktop\RunES.bat', shell = True)
p.communicate()
None of the above three methods is working. Let me know if anyone can help on this!!

Convert shell script command to command line

I am executing python script with multiple command line parameter, but using shell script.
command i execute for shell script execution is:
./scripts/run_qa.sh data/questions/questions.txt data/lexicons/paralex data/weights/paralex.txt data/database > output.txt
run_qa.sh files looks like below (please explain how it works):
#!/bin/bash
set -u
set -e
if [ $# != 4 ]; then
echo "Usage: run.sh questions lexicon weights db"
exit 1
fi
questions=$1
lexicon=$2
weights=$3
db=$4
PYTHONPATH=$PWD/python python -m lex.gearman_worker $lexicon $weights $db < $questions
I tried to execute python command as below in Command line :
python -m python/lex/gearman_worker.py data/lexicons/paralex data/weights/paralex.txt data/database > output.txt
which gives error :
/usr/bin/python: Import by filename is not supported.
Update1 :
gearman_worker.py file import other files like ths:
import lex.parse
import lex.semantics
from collections import namedtuple
from collections import defaultdict
import line gives error like this:
ImportError: No module named lex.lexicon
Update2 (executed on linux terminal):
export PYTHONPATH=$/mnt/paralex-evaluation-gearman/python
PYTHONPATH = ./python python -m python/lex/gearman_worker data/lexicons/paralex data/weights/paralex.txt data/database > output.txt
gives:
PYTHONPATH: command not found
Then
python -m python/lex/gearman_worker data/lexicons/paralex data/weights/paralex.txt data/database > output.txt
gives:
File "/mnt/paralex-evaluation-gearman/python/lex/gearman_worker.py", line 3, in <module>
import lex.lexicon
ImportError: No module named lex.lexicon
You just need to execute the following command:
PYTHONPATH=./python python -m lex.gearman_worker ARGUMENT_2 ARGUMENT_3 ARGUMENT_4 < ARGUMENT_1
If that doesn't work then you may have to export the PYTHONPATH setting:
export PYTHONPATH=${PWD}/python
python -m lex.gearman_worker ARGUMENT_2 ARGUMENT_3 ARGUMENT_4 < ARGUMENT_1
The original arguments that you would pass to the script are listed as ARGUMENT_N.
The script just:
sets some sensible defaults (see the documentation for set)
tests the the right number of arguments have been supplied
invokes the command above
Your attempt to invoke it:
misses the PYTHONPATH setting which is present in the script
passes the gearman_worker module as a file rather than a python module import

How do I create several commands with scriptine?

I have some code and I would like to use scriptine to create several commands for a single script. Here's my code so far:
from scriptine import run, path, log
import sys
import mymodule1 as m1
import mymodule2 as m2
def load_command():
'''
Load something
'''
m1.main()
def exec_command():
'''
Exec something
'''
m2.main()
if __name__ == '__main__':
run()
But when i run it, nothing happens. I cannot figure out what I'm missing. I've tested both main() functions inside each module and they're OK.
Thanks in advance
Your code works for me.
If you're running on Linux, I would add the first line to the .py file:
#!/usr/bin/env python
And then make it executable:
> chmod +x myfile.py
Then you can run your command like this:
> ./myfile.py load
> ./myfile.py exec
Otherwise, you can run your command like this:
> python myfile.py load
> python myfile.py exec

Categories