I want to resolve bugs of a complex python application written by someone else. I would like to set up Visual Studio Code [VSC] and its debugger so that I can step through the code.
The python application is meant to be run from a linux terminal using arguments, not as python. For this reason I am not able to set up VSC appropriately, nor to run the application's commands in python. As an example I recreated the application using two files:
File1 myprog:
#!/usr/bin/env python
import sys
def format():
#print(' myprog > format: sys.argv=',sys.argv)
import myprog
myprog.format_doc()
def main():
if len(sys.argv) >= 2:
command = sys.argv[1]
if command == '--version':
print('V1.0')
elif command == 'format':
eval(command+'()')
main()
File2 myprogr.py:
import os, sys
def format_doc():
print(' myprog.py > format_doc: sys.argv=',sys.argv)
print(' more complicated code I want to debug using several arguments')
When I run the application from terminal I see that the arguments are passed to File2 in sys.argv (I think as an effect of eval):
bash>./myprog format hello.txt --someoption
myprog.py > format_doc: sys.argv= ['./myprog', 'format', 'hello.txt']
more complicated code I want to debug using arguments
Can I set up VSC to run the above bash command and step into the python code?
Alternatively, can I run the methods in File2 from python so that I can easily debug it in VSC? As you can see I cannot add arguments using python because the python method accepts no input arguments:
>>> import myprog
>>> myprog.format_doc()
myprog.py > format_doc: sys.argv= ['']
more complicated code I want to debug using several arguments
>>> myprog.format_doc("hello.txt","--someoption","or_maybe_some_option")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: format_doc() takes 0 positional arguments but 1 was given
Related
I know this question has been asked in various variations but none of them seem to work for my specific case:
(btw all mentioned files are in my PATH)
I have a simple python script called test.py:
import sys
print('Hello world!')
print(sys.argv)
counter = 0
while True:
counter +=1
The counter is just there to keep the command window open so don't worry about that.
When I enter
test.py test test
into cmd I get the following output:
Hello world!
['C:\\Users\\path\\to\\test.py']
For some reason unknown to me the two other commands (sys.argv[1] and sys.argv[2]) are missing.
However when I create a .bat file like this:
#C:\Users\path\to\python.exe C:\Users\path\to\test.py %*
and call it in cmd
test.bat test test
I get my desired output:
Hello world!
['C:\\Users\\path\\to\\test.py', 'test', 'test']
I've read that the
%*
in the .bat file means that all command line arguments are passed to the python script but why are exactly these arguments not passed to the python script when I explicitly call it in cmd?
From what I've read all command line arguments entered after the script name should be passed to said script but for some reason it doesn't work that way.
What am I overlooking here?
I'm guessing that you need to actually run the script through the command line with C:\Users\path\to\python.exe test.py test test.
I'm not sure how Windows handles just test.py test test but from my limited experience it is probably just trying to open all 3 of those files. Since the first one (test.py) has a .py extension, it is opened with the Python Interpreter and is run automatically. The other two are not actually being passed in as an argument.
I would like to run my python script from the command line when supplies with some arguments. However, one of the arguments should be a list of options specific to a segment of the script.
Example:
MODULES_TO_INSTALL = ['sale','purchase','account_accountant',]
how can I do this: python fichier.py liste_modules_to_install
I've done something similar in the past. It might be easier if instead of sending them as a list already, you call your script like so,
python script.py module1 module2 ... moduleN
Then a simple line of code to read in these passed modules from command line would be,
import sys
MODULES_TO_INSTALL = sys.argv[1:]
I'm using similar approach to call python function from my shell script:
python -c 'import foo; print foo.hello()'
But I don't know how in this case I can pass arguments to python script and also is it possible to call function with parameters from command line?
python -c 'import foo, sys; print foo.hello(); print(sys.argv[1])' "This is a test"
or
echo "Wham" | python -c 'print(raw_input(""));'
There's also argparse (py3 link) that could be used to capture arguments, such as the -c which also can be found at sys.argv[0].
A second library do exist but is discuraged, called getopt.getopt.
You don't want to do that in shell script.
Try this. Create a file named "hello.py" and put the following code in the file (assuming you are on unix system):
#!/usr/bin/env python
print "Hello World"
and in your shell script, write something lke this
#!/bin/sh
python hello.py
and you should see Hello World in the terminal.
That's how you should invoke a script in shell/bash.
To the main question: how do you pass arguments?
Take this simple example:
#!/usr/bin/env python
import sys
def hello(name):
print "Hello, " + name
if __name__ == "__main__":
if len(sys.argv) > 1:
hello(sys.argv[1])
else:
raise SystemExit("usage: python hello.py <name>")
We expect the len of the argument to be at least two. Like shell programming, the first one (index 0) is always the file name.
Now modify the shell script to include the second argument (name) and see what happen.
haven't tested my code yet but conceptually that's how you should go about
edit:
If you just have a line or two simple python code, sure, -c works fine and is neat. But if you need more complex logic, please put the code into a module (.py file).
You need to create one .py file.
And after you call it this way :
python file.py argv1 argv2
And after in your file, you have sys.argv list, who give you list of argvs.
I know that I can run a python script from my bash script using the following:
python python_script.py
But what about if I wanted to pass a variable / argument to my python script from my bash script. How can I do that?
Basically bash will work out a filename and then python will upload it, but I need to send the filename from bash to python when I call it.
To execute a python script in a bash script you need to call the same command that you would within a terminal. For instance
> python python_script.py var1 var2
To access these variables within python you will need
import sys
print(sys.argv[0]) # prints python_script.py
print(sys.argv[1]) # prints var1
print(sys.argv[2]) # prints var2
Beside sys.argv, also take a look at the argparse module, which helps define options and arguments for scripts.
The argparse module makes it easy to write user-friendly command-line interfaces.
Use
python python_script.py filename
and in your Python script
import sys
print sys.argv[1]
Embedded option:
Wrap python code in a bash function.
#!/bin/bash
function current_datetime {
python - <<END
import datetime
print datetime.datetime.now()
END
}
# Call it
current_datetime
# Call it and capture the output
DT=$(current_datetime)
echo Current date and time: $DT
Use environment variables, to pass data into to your embedded python script.
#!/bin/bash
function line {
PYTHON_ARG="$1" python - <<END
import os
line_len = int(os.environ['PYTHON_ARG'])
print '-' * line_len
END
}
# Do it one way
line 80
# Do it another way
echo $(line 80)
http://bhfsteve.blogspot.se/2014/07/embedding-python-in-bash-scripts.html
use in the script:
echo $(python python_script.py arg1 arg2) > /dev/null
or
python python_script.py "string arg" > /dev/null
The script will be executed without output.
I have a bash script that calls a small python routine to display a message window. As I need to use killall to stop the python script I can't use the above method as it would then mean running killall python which could take out other python programmes so I use
pythonprog.py "$argument" & # The & returns control straight to the bash script so must be outside the backticks. The preview of this message is showing it without "`" either side of the command for some reason.
As long as the python script will run from the cli by name rather than python pythonprog.py this works within the script. If you need more than one argument just use a space between each one within the quotes.
and take a look at the getopt module.
It works quite good for me!
Print all args without the filename:
for i in range(1, len(sys.argv)):
print(sys.argv[i])
I am a newcomer to python (also very sorry if this is a newb question but) i have no idea what a command line argument is. when sys.argv is called, what exactly are the arguments? Any help with understanding this would be a great service.
Try running this program:
import sys
print(sys.argv)
You should see results similar to this:
% test.py
['/home/unutbu/pybin/test.py']
% test.py foo
['/home/unutbu/pybin/test.py', 'foo']
% test.py foo bar
['/home/unutbu/pybin/test.py', 'foo', 'bar']
% python test.py foo
['test.py', 'foo']
So, you see sys.argv is a list. The first item is the path to (or filename of) the script being run, followed by command-line arguments.
Given the command myscript.py arg1 arg2 arg3, the arguments are arg1, arg2 and arg3. sys.argv will also include the script name (i.e. myscript.py) in the first position.
Command line arguments are not specific to python.
Command line arguments are parameters you type after the script name. Eg. if you type: python test.py arg1, the first argument is arg1.
For examples, take a look at jhu.edu.
The command line arguments are the strings you type after a command in the command line, for instance:
python --help
Here --help is the argument for the python command, that shows a help page with the valid command line arguments for the python command.
In a python program, you have access to the arguments in sys.argv, so let's say you started a python script like this:
python myscript.py -x -y
When myscript.py starts, sys.argv[1] will have as value the string '-x' and sys.argv[2] will have as value the string '-y'. What you do with those arguments is up to you, and there are modules to help you easily define command line arguments, for instance argparse.
The arguments are usually used as a way of telling the program what it should do when it is run.
If I had a program named writefile.py, and I wanted the user to tell it which file to write, then I would run it with python writefile.py targetfile.txt. My sample writefile.py:
import sys
file = open(sys.argv[1], 'w') # sys.argv[0] = 'writefile.py' (unutbu's answer)
file.write('ABCDE')
file.close
After running this, I'll have a file named targetfile.txt with the contents "ABCDE". If I ran it with python writefile.py abcde.txt, I'd have abcde.txt with the contents "ABCDE".