This question already has answers here:
How can I specify working directory for a subprocess
(2 answers)
Closed 8 months ago.
im new to subprocessing and I have a question.
I can't find a proper solution online.
I want my path to be in a variable --> that will be passed to a function --> that will be passed to a subprocess.
I'm not allowed to show my real code, but this simple example (that I just can't get to work) would help me a lot.
This code snippet should do:
Just take my path from a variable.
"cd" the path in CMD.
Open a file that is located in this path.
So far I tried:
import subprocess
test_path = "C:/randome_path/.."
def Test_Function(test_path):
subprocess.call("cd", test_path, shell = True)
subprocess.call("python file.py", shell = True)
Test_Function()
My ErrorMessage is:
TypeError: Test_Function() missing 1 required positional argument: 'test_path'
Thank you for your time!
First you need to pass a parameter to your function because that's how you declarerd:
Test_Function(test_path) # here the function call with parameter
or using the key-value "approach"
another_path = # ...
Test_Function(test_path=another_path)
Second: the command is expecting a string not a further parameter
subprocess.call(f"python file.py", shell=True, cwd=test_path)
Note 1 to execute such command python file.py it is assumed that python's path is declared in some environment variable
Note 2 that subprocess may have some different "behaviour" under Windows
Try without shell=True. Now the commands should be given as a list of strings
def Test_Function(test_path):
subprocess.call(["python", "file.py"], cwd=test_path)
Related
This question already has answers here:
How to use argv with Spyder
(4 answers)
Closed last year.
I am struggling with passing 2 arguments in spyder using the command line. I have used the run-->configuration per file and in the command line options put JPEGtoPNG.py/Poxedex/new/. The JPEGtoPNG is the python file and the arguments to be passed are poxedex and new.
Dilemma:
When i run print(sys.argv[0]) it prints:
runcell(0, '/Users/chideraokafor/JPEGtoPNG.py')
which i understand is the default.
However when i run print(sys.argv[1]) it prints:
IndexError: list index out of range.
I have tried everything but still, it's not passing the two arguments, and I really don't want to use pycharm.
If Poxedex and new are command line arguments for a script, JPEGtoPNG.py, execution should be:
python JPEGtoPNG.py Poxedex new
Not / separated.
Note that the error you get is because you are not passing command line arguments and as such sys.argv is a list of length one (that one being the script name) and indexing starts at 0 in Python so accessing the second element via sys.argv[1] is indeed out of range.
Since Spyder provides a Python console and the options you are passing via the menu are intended as that - options and not arguments - you might find it easier to run the script(s) from the command line, for example using VSCode.
Even if you don't want to use VSCode, you can just open a terminal window and invoke the script from there. Just check your environment variables to ensure Python is on your system (or user) path.
This question already has answers here:
Display help message with Python argparse when script is called without any arguments
(18 answers)
Closed 3 years ago.
I am writting a new script and would like for the -h or --help argument to be called by default when the script is called without any parameters. So for example if someone calls command_line_utility.py then I want it to print the output you would get with command_line_utility.py -h.
I have dug around in the docs and looked at some examples, but all of them were specifying default argument values and not actually having arg parse call a default argument.
# Setting up Main Argument Parser
main_parser = argparse.ArgumentParser(description="A set of python web utility scripts")
main_parser.add_argument("-v",'--version', action='version', version='kuws V0.0.1')
# Setting up the main subparser
subparsers = main_parser.add_subparsers(help="Available commands found below, for more info on a command use: python command_line_utility.py <command> -h or kuws <command> -h")
"""Code below handles 'redirects' command in the main script
i.e. >python command_line_utility.py redirects or kuws redirects
"""
redirects_parser = subparsers.add_parser('redirects', argument_default='-u',
help='Allows you to trace redirects and get other information')
redirects_parser.add_argument('-u', "--url",
help='usage: python main.py redirects -u <url>; Lets you see the trace for a url', nargs='?', dest="trace_url")
As it stands when I run the file nothing actually gets printed to the command line. No help text or errors or anything.
I'm afraid argparse doesn't have any built-in support for this, but you can identify this situation and print the help message:
import sys
if len(sys.argv)==1:
parser.print_help(sys.stderr)
sys.exit(1)
Checking that len(sys.argv)==1 and in that case calling the print_help method of the parser as described in this answer to a similar question is a possible way to print the help message defined in the parser when no arguments are given.
When using subparsers, a common scheme is using set_defaults(func=<function to be called>) and then calling this function (as explained in sub-commands).
You can simply define a first set_defaults(func=help) at first that will be overwritten with the functions of your command.
Note that you can also make the command required when you declare your subparsers (add_subparsers(..., required='True')) and thus, when the user invokes without a command, she will get an error with the usage.
This question already has answers here:
subprocess.call() arguments ignored when using shell=True w/ list [duplicate]
(2 answers)
Python subprocess.call seems to ignore parameters
(2 answers)
Closed 4 years ago.
I am trying to automate nmap scans and I am using the subprocess module to do so. I am pretty much passing three variables to subprocess.call and having the command be run. Here is my code
import subprocess
TOOL = 'nmap'
joined = '-p1 5000'
target = 'localhost'
subprocess.call([TOOL, joined, target], shell=True)
This should lead to nmap -p1 5000 localhost being ran on my system which is a valid command, however, the call method seems to only be recognizing TOOL(nmap) and it just prints out the options for nmap. Does anyone know what I'm missing here?
I don't have nmap installed but you need set shell=False and split parameters:
import subprocess
TOOL = 'ls'
joined = '-a -l'
target = '/tmp'
print(subprocess.call([TOOL, *joined.split(), target], shell=False))
This question already has answers here:
Why does passing variables to subprocess.Popen not work despite passing a list of arguments?
(5 answers)
Closed 1 year ago.
I have a basic batch file that takes user input:
#echo off
set /p Thing= Type Something:
echo %Thing%
pause
However, I'd like to use a variable written in Python to pass into the batch file. Let's say just a string 'arg1' This is just a basic example, but I still cannot figure it out. The below code will run the batch process, but 'arg1' has no impact
import subprocess
filepath = r'C:\Users\MattR\Desktop\testing.bat'
subprocess.call([filepath, 'arg1'])
I have also tried p = subprocess.Popen([filepath, 'arg1']) but the batch file does not run in Python.
I have searched the web and SO, but none of the answers seem to work for me. Here are some links I've also tried: Example 1, Example 2. I've also tried others but they seem fairly specific to the user's needs.
How do I start passing Python variables into my batch files?
Your subprocess likely needs to run with a shell if you want bash to work properly
Actual meaning of 'shell=True' in subprocess
so
subprocess.Popen([filepath, 'arg1'], shell=True)
If you want to see the output too then:
item = subprocess.Popen([filepath, 'arg1'], shell=True, stdout=subprocess.PIPE)
for line in item.stdout:
print line
As a further edit here's a working example of what you're after:
sub.py:
import subprocess
import random
item = subprocess.Popen(["test.bat", str(random.randrange(0,20))] ,
shell=True, stdout=subprocess.PIPE)
for line in item.stdout:
print line
test.bat
#echo off
set arg1=%1
echo I wish I had %arg1% eggs!
running it:
c:\code>python sub.py
I wish I had 8 eggs!
c:\code>python sub.py
I wish I had 5 eggs!
c:\code>python sub.py
I wish I had 9 eggs!
Here is how I managed to call a variable from python to batch file.
First, make a python file like this:
import os
var1 = "Hello, world!"
os.putenv("VAR1", var1) #This takes the variable from python and makes it a batch one
Second, make your batch file, by going to the folder where you want your python program to work, then right-clicking in the map, then create new text file. In this text file, write whatever you want to do with the variable and make sure you call your variable using %...% like so:
echo %VAR1%
Save this file as a batch file like so: file>save as>name_of_file.bat then select: save as file: all files.
Then to call your batch file in python, write:
os.system("name_of_file.bat")
Make sure all these files are in the same map for them to work!
There you go, this worked for me, hopefully I can help some people with this comment, because I searched for so long to find how this works.
PS: I also posted on another forum, so don't be confused if you see this answer twice.
This question already has answers here:
How to redirect output with subprocess in Python?
(6 answers)
Closed 7 years ago.
In my python script,
I am trying to run a windows program that prints output.
But I would like to redirect that output to a text file.
I tried
command = 'program' + arg1 + ' > temp.txt'
subprocess.call(command)
Where program is my program name and arg1 is argument it takes.
but it does not redirect the output to the text file
It just prints that on the screen.
Can anyone help me how to do this?
Thank you!
Pass a file object to the stdout parameter of subprocess.call():
with open('myoutfilename', 'w') as myoutfile:
subprocess.call(cmd, stdout=myoutfile)
You can use shell=True in subprocess.call
However, a (much) better way to do this would be:
command = ['program',arg1]
with open('temp.txt','w') as fout:
subprocess.call(command,stdout=fout)
This removes the shell from the whole thing making it more system independent, and it also makes your program safe from "shell injection" attacks (consider arg1='argument; rm -rf ~' or whatever the windows equivalent is).
The context manager (with statement) is a good idea as it guarantees that your file object is properly flushed and closed when you leave the "context".
Note that it is important that if you're not using shell=True to a subprocess.Popen (or similar) class, you should pass the arguments as a list, not a string. Your code will be more robust that way. If you want to use a string, python provides a convenience function shlex.split to split a string into arguments the same way your shell would. e.g.:
import subprocess
import shlex
with open('temp.txt','w') as fout:
cmd = shlex.split('command argument1 argument2 "quoted argument3"'
#cmd = ['command', 'argument1', 'argument2', 'quoted argument3']
subprocess.call(cmd,stdout=fout)