PYTHON Script not using OS Commands - python

Within a UBUNTU VM, using GNS3 I created code that is an attempt to after the user's input perform one of 3 different outcomes, however, the if statements don't work, the python files can't be found which I was trying to point to this the cd/home.. command. And the curl commands are apparently the incorrect syntax even though that is what I would enter for them to work. please help me out and get this working.
This is what I tried:
#!/usr/bin/python3
import os
import subprocess
Code = input("Enter RYU, ONOS or CURL:")
print("Command entered was: " + Code)
if input == 'RYU':
os.system('rest_router.py')
os.system('gui_topology.py')
elif input == "ONOS":
os.system('sudo /opt/onos/bin/onos-service start')

You are using single quotes to quote something that already has single quotes. By doing so, what should be an opening quote in your curl command is now effectively a closing quote in your Python, and Python doesn't understand why there is now a random ( there where Python code should continue.
I underlined what is quoted in the following examples. Note that even syntax highlighting in most any editor (and also here on Stack Overflow) is helping you see what is inside a string and what is not, colouring them differently (though syntax highlighting can be fallible):
echo 'foo' bar
---
But:
os.system('echo 'foo' bar')
----- ----
To fix, you can escape the inner quotes, so Python treats them as any regular character inside the string:
os.system('echo \'foo\' bar')
----------------
Or you can change the outer quotes. Python has several sets of quotes; you can't use ' or " since you're already using both of them inside the string, but you can use ''' or """:
os.system('''echo 'foo' bar''')
--------------

Related

Typing effect Python [duplicate]

I am writing a program in Python and want to replace the last character printed in the terminal with another character.
Pseudo code is:
print "Ofen",
print "\b", # NOT NECCESARILY \b, BUT the wanted print statement that will erase the last character printed
print "r"
I'm using Windows8 OS, Python 2.7, and the regular interpreter.
All of the options I saw so far didn't work for me. (such as: \010, '\033[#D' (# is 1), '\r').
These options were suggested in other Stack Overflow questions or other resources and don't seem to work for me.
EDIT: also using sys.stdout.write doesn't change the affect. It just doesn't erase the last printed character. Instead, when using sys.stdout.write, my output is:
Ofenr # with a square before 'r'
My questions:
Why don't these options work?
How do I achieve the desired output?
Is this related to Windows OS or Python 2.7?
When I find how to do it, is it possible to erase manually (using the wanted eraser), delete the '\n' that is printed in python's print statement?
When using print in python a line feed (aka '\n') is added. You should use sys.stdout.write() instead.
import sys
sys.stdout.write("Ofen")
sys.stdout.write("\b")
sys.stdout.write("r")
sys.stdout.flush()
Output: Ofer
You can also import the print function from Python 3. The optional end argument can be any string that will be added. In your case it is just an empty string.
from __future__ import print_function # Only needed in Python 2.X
print("Ofen",end="")
print("\b",end="") # NOT NECCESARILY \b, BUT the wanted print statement that will erase the last character printed
print("r")
Output
Ofer
I think string stripping would help you. Save the input and just print the string upto the length of string -1 .
Instance
x = "Ofen"
print (x[:-1] + "r")
would give you the result
Ofer
Hope this helps. :)

How to remove whitespaces from multiline string pass it to another program and then add back whitespaces?

Summary
I need to detect indentation level of the first line in multiline string passed to a script. Store it. Remove this indent from other lines. Pass the multiline string with removed indent level to another program (that I've figured how to do) add back indent to all lines in multiline string and print it to stdout (that I also know how to do).
To be specific I have a problem with vim and Python formatter YAPF.
The way yapf works is that if python file is incorrect formatting would result in error.
So imagine this
def f():
# imagine some very very long lines here that we want to reformat
If I would select this imagined lines in vim and then press gq (I've set formatprg=yapf) vim would substitute this lines with a traceback of yapf which is no good of course. But If I would select the whole function it would do the job perfectly.
You can test this with
echo ' fooo = 1' | yapf
This would result in IndentationError
While echo 'fooo = 1' | yapf would work
So what I think is a very nice workaround is to remove indentation store the indent level of the first line, pass string without indentation to yapf somehow and then add indent to the result. The problem with this is I'd like this to be a one liner or close to that so that it could be stored directly in my vimrc. So python isn't a good match for that because I would need at least to import re package etc.
So I thought about perl.
The only problem is that I don't know perl much.
So for now my experiment looks like this
$a = " foo = 1\n bar = '1'";
my ($indent, $text) = $a =~ m/^(\s+)(.*)$/m;
$command = "echo " . $text;
$out = `$command`;
print "$out\n";
print "$text\n";
I will be glad for any help. Maybe there is more easy way to do this, I don't know.
Since you seem to be familiar with Python already I would recommend using its textwrap module, which contains dedent and (in version 3.3 and later) indent functions that can do most of the job for you:
import re
from textwrap import dedent, indent
whitespace = re.compile('\s+')
test_string = ''' while True:
pass'''
leading_whitespace = whitespace.match(test_string)
dedented_text = dedent(test_string)
# Do whatever you want with dedented_text
indented_text = indent(dedented_text, leading_whitespace.group(0))

Use raw string to run a sub process

This is kind of weird, but I am running a program called scrapebox, scrapebox has an automator plugin that creates a file to automagically run a few things within. In order to run the automator from cmd I would cd into the program directory then type:
Scrapebox.exe "automator:1.sbaf"
It would first launch Scrapebox the program, once open, it would immediately run the automated file.
This is a small piece in a much bigger puzzle. I am trying to call that within a larger Python script.
import os
import subprocess
..........
..........
..........
print "Opening Scrapebox now, please wait."
os.chdir('C:\Users\Admin\DomainDB\Programs\ScrapeBox')
print
print "Current working dir : %s" % os.getcwd()
print
subprocess.call(["Scrapebox.exe"])
#"automator:1.sbaf"
print "Scrapebox finished. Moving on."
When I run it as above, it works and opens scrapebox. But, what I really need to do is something like this:
subprocess.call(["Scrapebox.exe "automator:1.sbaf""])
When I do that it throws a syntax error. So how can I input that maybe as a raw string as though it were being typed into cmd?
If you want to embed double quotes in a string, you can use one of a number of ways. Also to pass a single string of all arguments, don't pass as a list []:
subprocess.call("Scrapebox.exe \"automator:1.sbaf\"")
subprocess.call('Scrapebox.exe "automator:1.sbaf"')
Python can use either single- or double-quotes around a string. You can also triple-quote a string (three single- or double-quotes at the start and end), which allows newlines as well, but it is not needed here.
If you pass a list of arguments, each argument should be an element of the list:
subprocess.call(['Scrapebox.exe','automator:1.sbaf'])

Python system argument reading '&'

I want to pass url to my python via the console and then do the appropriate tasks. many of the links contain the character '&' in the link. python interprets that as ending the argument this however is not what I want. here is a sample of the code
import sys
external_id = sys.argv[1].encode("utf-8")
print external_id
And when I run the following:
python graph.py 2%60&7
I get:
2%60
How do I make python interpret the '&' as nothing more than another character in the url?
This is not python, it's bash. You need to escape it:
python graph.py 2%60\&7
Quoting this answer:
The & informs the shell to put the command in the background.
Python never receives that character because the shell takes care of it, thus this isn't an issue of Python. You can also wrap 2%60&7 with quotes to make it work
me#pc:~$ python3 script.py '2%60&7'
b'2%60&7'
Sometimes escaping & is a lot harder than doing this.

Passing double quotation marks to a command from Python using the subprocess module

I have a command line program I'm using from within a Python script to take care of stamping a build number onto an executable.
This is the command line program: http://www.elphin.com/downloads/stampver/
My problem is that the program takes double quotes (") in one of its arguments and the Python subprocess module I'm using to call this program keeps prepending a backslash onto the double quotes when executing the program. This causes the program to fail due to incorrect syntax.
It is expecting a command like: StampVer.exe -nopad -k -f"0.1.4491.0" <ExeFile>.exe
And instead Python is executing: StampVer.exe -nopad -k -f\"0.1.4491.0\" <ExeFile>.exe
I've tried a few things that I've found here on StackOverflow for similar sounding problems such as marking the string as raw or adding backslashes before the quotes in Python; which just results in triple backslashes on the command line instead of one, because Python then tries to escape the backslash as well as the double quote.
Should I be using something other than the subprocess module to accomplish this or do all these types of modules in Python follow the same rules for escaping characters? Is there something I can do to tell subprocess to strip escape characters or to not add them at all?
EDIT
This is how I'm calling subprocess from Python:
def set_file_version(version_number, filepath):
try:
file_version_arg = '-f"{0}"'.format(version_number)
cmd_line = ["StampVer.exe", "-nopad", "-k", file_version_arg, filepath]
subprocess.check_output(cmd_line)
except subprocess.CalledProcessError as e:
if e.returncode == 1:
pass
else:
raise e
StampVer then returns this:
error: Invalid -f parameter. Try -f"0.0.0.0" Use StampVer -? for help
try this script sub.py:
#! /usr/bin/python
import sys
from subprocess import check_output
if len(sys.argv) > 1:
print sys.argv
else:
print check_output((sys.argv[0], '-f"1234"'))
then run it:
./sub.py
it return what we gave:
['./sub.py', '-f"1234"']
So I guess check_output works just fine, the problem may came from how StampVer.exe handle parameter, you can try
file_version_arg = '-f{0}'.format(version_number)
My solution ended up being kind of a cop-out. Despite the documentation for StampVer showing the format above for the version number in all examples, it turns out you can just leave the quotes out all together and even space it out from the -f switch and it will still be accepted.
I'm going to call this my answer but I still think being able to pass quotes through subprocess is a worthwhile problem to figure out. If anyone has an answer that will actually solve the initial problem then please post it and I'll mark it instead.

Categories