I am trying to use Python to run an executable (Windows 7) with parameters. I have been able to make the program run, but the amount of parameters I can use that will prove the Python script worked with parameters is limited. The best one is formatted like so:
-debugoutput debug.txt
I have tested this using a windows shortcut with an edited target and it works, it creates a debug output in the program directory.
Here is the code I am using:
import subprocess
args = [r"C:\Users\MyName\LevelEditor\LevelEditor.exe", "-debugoutput debug.txt"]
subprocess.call(args)
This does run the program, but the debug output is not created. I have tried putting an "r" in front of the parameter but this made no difference. I assume it is a simple formatting error but I can't find any examples to learn from that are doing the same thing.
UPDATE:
Thanks for the answers everyone, all the same, simple formatting error indeed.
In-code definition results in invocation of shell command line:
C:\Users\MyName\LevelEditor\LevelEditor.exe "-debugoutput debug.txt"
As you can see, by merging -debugoutput debug.txt to single list element, you explicitly stated that space between them shouldn't be parsed as command line argument separator.
To achieve expected behavior put file name string as separate element to argument list.
[r"C:\Users\MyName\LevelEditor\LevelEditor.exe", "-debugoutput", "debug.txt"]
As far as I know you need to split the arguments by the space, so your args would look like:
args = [r"C:\Users\MyName\LevelEditor\LevelEditor.exe", "-debugoutput", "debug.txt"]
Does that work?
I do not know if it works, but
import subprocess
args = [r"C:\Users\MyName\LevelEditor\LevelEditor.exe", "-debugoutput", "debug.txt"]
subprocess.run(args)
Following the docs
Related
I know a very similar question has already been asked but since none of the solutions posted there worked for my problem I try to make it replicable:
So I'm calling this script to merge some shapefiles (all files in one folder) like this:
shpfiles = 'shapefile_a.shp shapefile_b.shp'
subprocess.call(['python', 'shapemerger.py', '%s' % shpfiles])
I only get the Usage Instructions from the script so I cant determine what goes wrong. If i call the script directly in the terminal it works.
Any help is appreciated.
Every time a program is started, it receives a list of arguments it was invoked with. This is often called argv (v stands for vector, i.e. one-dimensional array). The program parses this list, extracts options, parameters, filenames, etc. depending on its own invocation syntax.
When working at the command line, the shell takes care of parsing the input line, starting new program or programs and passing them their argument list.
When a program is called from another program, the caller is responsible to provide the correct arguments. It could delegate this work to shell. The price for it is very high. There is substantial overhead and possibly a security risk! Avoid this approach whenever possible.
Finally to the question itself:
shpfiles = 'shapefile_a.shp shapefile_b.shp'
subprocess.call(['python', 'shapemerger.py', '%s' % shpfiles])
This will invoke python to run the script shapemerger.py with one argument shapefile_a.shp shapefile_b.shp. The script expects filenames and receives this one name. The file "shapefile_a.shp shapefile_b.shp" does not exist, but the script probably stops before attempting to access that file, because it expect 2 or more files to process.
The correct way is to pass every filename as one argument. Assuming shpfiles is a whitespace separated list:
subprocess.call(['python', 'shapemerger.py'] + shpfiles.split())
will generate a list with 4 items. It is important to understand that this approach will fail if there is a space in a filename.
I have looked at the suggested similar questions and whilst useful, do not actual match my problem and I'm still struggling.
I am using a batch file to run a series of python files, and one of these python scripts returns a variable to be used as an argument in a later script (it has to be exported to console because it is also used as a parameter in an executable.)
By batch file looks like this:
#echo off
#title AutoStats
set raw_dir ='raw_directory'
set today_dir ='today_directory'
set archive_dir='archive_directory'
set error_file='error_directory'
set DateEstate='dE'
set OTQ_File='OTQ_File'
cd C:\dev\OTQtxt
for /f "delims=" %%a in ('get_date.py') do set $date=%%a
python create_csv.py %$date% %raw_dir% %archive_dir% %error_file%
pause
The python script looks like this:
from sys import argv
date, raw_dir, today_dir, archive_dir, error_file = argv[1:]
print date
print raw_dir
print today_dir
print archive_dir
print error_file
The reason for using argv[1:] is because I don't want to use the script name as an argument
In the future it will obviously do more than this, this is just for testing whether I can get the arguments in.
The error is as the title states. This only occurs when running it from the batch file, if I run it from powershell and type in the arguments myself then it works.
I find it odd that when typing the arguments myself in powershell the script works fine, when using the parameters set in the .bat it returns an error.
Can anybody shed some light on why this might be. I've never used batch files until now so it might just be a simple mistake.
Whilst the problem pointed out by Ffisegydd was correct, the real mistake causing the problem to happen with a different number of argument was with with setting of parameters in the batch file.
for the first 2 set lines I added a space after the parameter name:
set today_dir ='today_directory'
should have been:
set today_dir='today_directory'
Is anyone able to tell me how to write a conditional for an argument on a python script? I want it to print "Argument2 Entered" if it is run with a second command line arguments such as:
python script.py argument1 argument2
And print "No second argument" if it is run without command line arguments, like this:
python script.py argument1
Is this possible?
import sys
if len(sys.argv)==2: # first entry in sys.argv is script itself...
print "No second argument"
elif len(sys.argv)==3:
print "Second argument"
There are many answers to this, depending on what exactly you want to do and how much flexibility you are likely to need.
The simplest solution is to examine the variable sys.argv, which is a list containing all of the command-line arguments. (It also contains the name of the script as the first element.) To do this, simply look at len(sys.argv) and change behaviour based on its value.
However, this is often not flexible enough for what people expect command-line programs to do. For example, if you want a flag (-i, --no-defaults, ...) then it's not obvious how to write one with just sys.argv. Likewise for arguments (--dest-dir="downloads"). There are therefore many modules people have written to simplify this sort of argument parsing.
The built-in solution is argparse, which is powerful and pretty easy-to-use but not particularly concise.
A clever solution is plac, which inspects the signature of the main function to try to deduce what the command-line arguments should be.
There are many ways to do this simple thing in Python. If you are interested to know more than I recommend to read this article. BTW I am giving you one solution below:
import click
'''
Prerequisite: # python -m pip install click
run: python main.py ttt yyy
'''
#click.command(context_settings=dict(ignore_unknown_options=True))
#click.argument("argument1")
#click.argument("argument2")
def main(argument1, argument2):
print(f"argument1={argument1} and argument2={argument2}")
if __name__ == '__main__':
main()
Following block should be self explanatory
$ ./first.py second third 4th 5th
5
$ cat first.py
#!/usr/bin/env python
import sys
print (len(sys.argv))
This is related to many other posts depending upon where you are going with this, so I'll put four here:
What's the best way to grab/parse command line arguments passed to a Python script?
Implementing a "[command] [action] [parameter]" style command-line interfaces?
How can I process command line arguments in Python?
How do I format positional argument help using Python's optparse?
But the direct answer to your question from the Python docs:
sys.argv -
The list of command line arguments passed to a Python script. argv[0] is the script name (it is operating system dependent whether this is a full pathname or not). If the command was executed using the -c command line option to the interpreter, argv[0] is set to the string '-c'. If no script name was passed to the Python interpreter, argv[0] is the empty string.
To loop over the standard input, or the list of files given on the command line, see the fileinput module.
I'm trying to create a program that can be called from the command line and use keyword arguments in python 2.6. So far I've tried:
#!/usr/bin/python
def read(foo = 5):
print foo
return 0
if __name__ == '__main__'
read()
When I try to run this from the command line: ./test.py the program prints 5 as expected. Is there a way to use ./test.py foo=6? I want to preserve the keyword arguments.
It seems like a simple question, but I haven't found a good source for this.
python has built in library to help you achieve passing command line arguments to a script
argparse. THe usage is a little different then what you are describing in your question though...
On a basic level you can access all command line arguments by sys.argv, which will be a list of arguments
Sorry should have mentioned the python 2.6 library is called optparse
Something like this?
if __name__ == '__main__':
kwargs = dict(x.split('=', 1) for x in sys.argv[1:])
read(**kwargs)
That said, argparse and optparse are probably going to give you something more robust and more natural for someone used to the commandline. (Not to mention, supporting arguments of types other than string.)
Oh, and if what you're really after is just interactive use of your function, use the interactive interpreter; either python or ipython. You'd need to put the code into a file ending in .py and import it, then you could just call it.
A less usual, but very interesting alternative is docopt: a library that generates an argument parser from the help message that you write for your program (on github).
I have a script which takes in few arguments
./hal --runtest=example
where example = /home/user/example.py
how can I pass these arguments in shell script?
I'm having trouble figuring out what you're asking, but assuming your question is "How can a shell script pass dynamic arguments to a command that happens to be written in Python" and you are using a Bourne-family shell (very likely), the simplest correct answer would be
example=/home/user/example.py
./hal "--runtest=$example"
The shell will resolve the quoting and the script will see --runtest=/home/user/example.py without breaking if you later decide to pass in a path containing spaces.
Take a look a the following:
http://lowfatlinux.com/linux-script-variables.html
It is Bash specific though and as per comments above not sure which shell you're using.
Here you'll find all you need in terms of how to pass an argument to a shell script.