How do I pass python variables to subprocess call to sed? - python

I'm trying to send a call to sed but it seems like it is not processing the variables it looks correct when I print it but it not correct in the call
#!/usr/bin/python -tt
import json
from pprint import pprint
from subprocess import call
with open('admin_list.json') as data_file:
admins = json.load(data_file)
#pprint(data[0]["key"])
for admin in admins:
#print(admin["name"])
#print (" sudo sed, 1 a ${"+admin['key']+"} /home/"+admin['name']+"/.ssh/authorized_keys")
call(["sudo sed", "1 a ${"+admin['key']+"} /home/"+admin['name']+"/.ssh/authorized_keys"])
OSError: [Errno 2] No such file or directory"
I've updated my code I do not get errors but the file still is not updated
#!/usr/bin/python -tt
import json
import os
from pprint import pprint
from subprocess import call
with open('admin_list.json') as data_file:
admins = json.load(data_file)
#pprint(data[0]["key"])
for admin in admins:
call(["sudo","sed", "1 a "+admin['key']+"","/home/"+admin['name']+"/.ssh/authorized_keys"])
call(['cat','/home/'+admin["name"]+'/.ssh/authorized_keys'])

You have to split your arguments properly else spaces will be interpreted literally
Here you have 4 arguments:
sudo
sed
argument of sed
file to parse as admin
And don't rely on env. variables, evaluate them beforehand (else you'll need shell=True)
so pass a 4-item list to call
call(["sudo","sed", "1 a "+os.getenv(admin['key']),"/home/"+admin['name']+"/.ssh/authorized_keys"])
note that to modify your file in-place you need to add -i option to sed:
call(["sudo","sed", "-i", "1 a "+os.getenv(admin['key']),"/home/"+admin['name']+"/.ssh/authorized_keys"])

Related

how to run an executable with python json

so I have this executable binary file that can be run via terminal
and by python
using code
$`python3 shell_c.py`
where python file contains
import subprocess
def executable_shell():
x=subprocess.run('cd build && ./COSMO/methane_c0.outmol.cosmo', shell=True, capture_output=True)
print(x)
executable_shell()
where COSMO is my executable name and "methane_c0.outmol" is the dynamic value that should be changed along with ".cosmo" which is an extension)
so to get these values from the JSON file I have created a JSON file
with input
{
"root_directory": "C:\\Users\\15182\\cosmo theory\\COSMO\\UDbase8",
"file_name": "methane_c0",
"file_format": ".cosmo",
"output1": "N_atoms",
"output2": "total number of segments"
}
now all that is left is to pass the value of file_name and file_format to the subprocess code to run it.
but I am not getting how to do go about it.
code I have written so far is basic
import json
with open ("parameters.json") as file:
data =json.load(file)
print(type(data))
pront(data)
how should I go so that values can be passed to a python file?
Something like this?
import json
import subprocess
with open ("parameters.json") as file:
data =json.load(file)
dynamic_file_name = data['file_name']+'.outmol'+data['file_format']
def executable_shell():
x=subprocess.run('cd build && ./COSMO/'+dynamic_file_name, shell=True, capture_output=True)
print(x)
executable_shell()

Error: More than one file name has been given

I want to change tags of my all mkv files.
I installed MKVToolNix.
My code is:
#!/usr/bin python3
# -*- coding: utf-8 -*-
import os
import subprocess
import re
neredebu='/home/pi/hrc2/Film-Dizi/duzenle'
for kokdizin, altdizinler, dosyalar in os.walk(neredebu):
for dosya in dosyalar:
if dosya.endswith('.mkv'):
isim=re.findall('([\w\d.]*)\.[\d]{4}\.m1080p.',dosya)[0]
isim=isim.replace(".", " ")
yil=re.split('[\w\d.]*\.([\d]{4})\.m1080p.',dosya)[1]
title=isim+" - "+yil+" _ www.netmanyagi.com"
dosyayolu=kokdizin
dosyatam=dosyayolu+"/"+dosya
bashCommand = "mkvpropedit "+dosyatam+" --edit info --set \"title="+title+"\""
process = subprocess.Popen(bashCommand.split(), stdout=subprocess.PIPE)
output, error = process.communicate()
#output = subprocess.check_output(['bash','-c', bashCommand])
print(output)
print("---")
I'm getting this output:
b"Error: More than one file name has been given ('/home/pi/hrc2/Film-Dizi/duzenle/The' and 'Hero').\n"
---
What is the cause of this error?
The issue is that one of your .mkv files contains a space in its filename. Thus when you split the bashCommand to create a list, you inadvertently split the filename into two pieces.
The easiest thing would be to rename the file so that it doesn't contain a space. It may also be safer to build the list manually, rather than relying upon split(), and ensure you wrap the filename in quotes.
bashCommand = [
'mkvpropedit',
'"{}"'.format(dosyatam),
'--edit',
'info',
'--set',
'"title={}"'.format(title)
]
process = subprocess.Popen(bashCommand, stdout=subprocess.PIPE)

Pass the variable and value from python to bash

I would like to pass the variable "NUMBER_CAMS" and value from my python script to a bash environmental file "env_roadrunner"
following is the code that i have written
import subprocess
import os
import sys
import ConfigParser
os.chdir("/home/vasudev/LTECamOrchestrator_docker/tools/")
NUMBER_CAMS=sys.argv[2]
cmd = "xterm -hold -e sudo /home/vasudev/LTECamOrchestrator_docker/tools/create_pcap_replay_encoder " \
" /home/vasudev/LTECamOrchestrator_docker/tools/env_roadrunner"
p = subprocess.Popen([cmd] , shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Following is my bash script which takes environmental variables
#!/bin/bash
# the name or ip address of the orchestrator
ORCHESTRATOR_IP="192.168.212.131"
# the port of the orchestrator
ORCHESTRATOR_PORT=9000
# password for the admin user
ORCHESTRATOR_PASSWORD='.qoq~^c^%l^U#e~'
# number of cameras to create from this pcap file
NUMBER_CAMS="$N"
# three port numbers that are only used internally but need to be free
I wanted to pass the value NUMBER_CAMS through my python script but i am getting following error
Traceback (most recent call last):
File "/home/vasudev/PycharmProjects/Test_Framework/Stream_provider.py", line 19, in <module>
NUMBER_CAMS=sys.argv[2]
IndexError: list index out of range
any suggestions why i am getting index out of range error
You to set the value of N in the environment so that your script can see that value to assign to NUMBER_CANS.
import subprocess
import os
import sys
import ConfigParser
os.environ["N"] = "2" # Must be a string, not an integer
cmd = ["xterm",
"-hold",
"-e",
"sudo",
"-E",
"./create_pcap_replay_encoder",
"env_roadrunner"]
p = subprocess.Popen(cmd,
cwd="/home/vasudev/LTECamOrchestrator_docker/tools/"
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
Note that sudo ignores the current environment by default when running a command; the -E option I added allows create_pcap_replay_encoder to see the inherited environment. However, you can only use -E if sudo is configured to allow the environment to be preserved.

Manipulating stdin and redirect to stdout in Python

I'm trying to write a simple python script where
it takes values from stdin
replaces a specific matched word
passes on the output with the NEW value back to stdout
I only have the part where it takes the values from stdin and looks for the matching words, I'm a bit stuck after that.
import re
import sys
for line in sys.stdin:
matchObj = re.search(r'<something>(.*)</something>',line)
if matchObj:
oldWord = matchObj.group(1)
print oldWord
Contents of foo
<something>REPLACEME</something>
<blah>UNTOUCH</blah>
Ideally if I run this command
cat foo | ./test.py
I would get something like this
<something>NEWWORD</something
<blah>UNTOUCH</blah>
Are you looking for re.sub?
import re
import sys
for line in sys.stdin:
sys.stdout.write(re.sub(r'(<something>)REPLACEME(</something>)',
r'\1NEWWORD\2',
line))
Running the above on your example data:
$ echo '<something>REPLACEME</something>\n<something>UNTOUCH</something>' | python2 test.py
<something>NEWWORD</something>
<blah>UNTOUCH</blah>
Note that parsing XML with regular expressions is probably a bad idea. The Python standard library comes with a number of XML modules.
Here's an example:
import sys
import xml.etree.ElementTree
tree = xml.etree.ElementTree.parse(sys.stdin)
root = tree.getroot()
for node in root.iter('something'):
if node.text == 'REPLACEME':
node.text == 'NEWWORD'
tree.write(sys.stdout)
The above would work just the same:
$ echo '<root><something>REPLACEME</something>\n<blah>UNTOUCH</blah></root>' | python2 test.py
<root><something>REPLACEME</something>
<blah>UNTOUCH</blah></root>
firs if you run cat foo | ./test.py you got test.py: command not found , you need to run this : cat foo |python ./test.py .
then the output of your code will be :
REPLACEME
but for the output that you want, you need to use re.sub():
import re
import sys
for line in sys.stdin:
matchObj = re.sub(r'<something>(.*)</something>','<something>NEWWORD</something>',line)
if matchObj:
print matchObj
output :
<something>NEWWORD</something>
<blah>UNTOUCH</blah>
Also as a pythonic way you can use The ElementTree XML API

How to parse JSON passed on the command line

I am trying to pass JSON parameters through command line in Python:
automation.py {"cmd":"sel_media","value":"5X7_photo_paper.p}
how can I extract the values sel_media and 5X7_photo_paper.p?
I used the following code, but it is not working:
cmdargs = str(sys.argv[1])
print cmdargs
Provided you pass actual valid JSON to the command line and quote it correctly, you can parse the value with the json module.
You need to quote the value properly, otherwise your shell or console will interpret the value instead:
automation.py '{"cmd":"sel_media","value":"5X7_photo_paper.p"}'
should be enough for a bash shell.
In Python, decode with json.loads():
import sys
import json
cmdargs = json.loads(sys.argv[1])
print cmdargs['cmd'], cmdargs['value']
Demo:
$ cat demo.py
import sys
import json
cmdargs = json.loads(sys.argv[1])
print cmdargs['cmd'], cmdargs['value']
$ bin/python demo.py '{"cmd":"sel_media","value":"5X7_photo_paper.p"}'
sel_media 5X7_photo_paper.p
The above is generally correct, but I ran into issues with it when running on my own python script
python myscript.py '{"a":"1"}'
does not work directly in my terminal
so I did
python myscript.py '{\"a\":\"1\"}'

Categories

Resources