Adding paths to arguments in popen - python

I want to execute a Linux command through Python. This works in the terminal:
/usr/bin/myprogram --path "/home/myuser"
I've tried this:
path = "/home/myuser"
args = ['/usr/bin/myprogram', '--path ' + path]
proc = subprocess.Popen(args)
And this:
path = "/home/myuser"
args = ['/usr/bin/myprogram', '--path "' + path + '"']
proc = subprocess.Popen(args)
But myprogram does not accept the path formatting. I know that paths behave differently when not executing as shell but I can't get it working. I've also tried single quoting the path instead of double quoting it. Bonus points for a solution that also works on Windows (with a different program path, obviously).
EDIT: Sorry, was writing this out from memory and used backslashes instead of forward slashes. The actual code did use the (correct) forward slashes.

Here's something to try:
import subprocess
import shlex
p = subprocess.Popen(shlex.split("/usr/bin/myprogram --path /home/myuser")
Mind the forward slashes ("/"). From what I read, Python doesn't like backslashes ("\") even when running on Windows (I've never used it on Windows myself).

The problem comes from your string literal, '\usr\bin\myprogram'. According to escaping rules, \b is replaced by \x08, so your executable is not found.
Pun an r in front of your string literals (i.e. r'\usr\bin\myprogram'), or use \\ to represent a backslash (i.e. '\\usr\\bin\\myprogram').

Related

Using python to insert a single escape character in front of specified character in a string

I have a path string that I would like to use inside of a subprocess command. This path contains directories with a whitespace, so a string like "foo/foo bar/bar" would need to be converted to "foo/foo\ bar/bar" beforehand. I have tried
path = "foo/foo bar/bar"
path = path.replace(" ","\\ ")
which results in "foo/foo\\ bar/bar"
I have also tried
path = os.path.normpath(path)
which changes nothing and
path = repr(path.replace(" ","\\ "))
which returns "foo/foo\\\\ bar/bar"
Is there a good solution to this while still using subprocess or os.system to call the command?
You must be expecting to put the entire command in a string and letting a shell parse it. Call subprocess with a list of arguments to avoid any need for quoting:
path = "foo/foo bar/bar"
subprocess.run(["ls", "-l", path])

Open a command prompt at a specific location followed by running a script at that location with some command line arguments using python

I was able to open command prompt and change the directory to required location using the subprocess module, but I was unable to pass further arguments to run an application along with some command line arguments. I am new to the subprocess module, so I did some search over stackoverflow couldn't find the desired result.
Mycode:
import subprocess
path = r"C:/Users/Application_Folder"
p = subprocess.Popen(r"cmd.exe", cwd="C:/Project_Files", shell=True)
Desired output:
Path: C:\Users\Application_folder\Application.exe
Need to open the cmd prompt in windows at the Application_folder location,
run the Application.exe by passing some command line arguments, using python
Just pass the command line you actually want to execute, with the executable path and whatever arguments you want to pass:
command_line = [r'C:\Users\Application_Folder\Application.exe', '/argument1', '/argument2']
p = subprocess.Popen(command_line, cwd=r'C:\Project_Files')
A couple of notes to keep in mind:
You shouldn't use shell=True. It's not necessary here -- in fact it's almost never necessary -- but it does introduce a potential security risk.
The whole point of raw string literals (starting with r' or r") is to change how backslash characters within the string are interpreted. r'C:\Program Files' is exactly the same string as "C:\\Program Files". If your string doesn't have backslashes in it, don't bother using the r prefix.

Xcopy with Python

I'm trying to get xcopy working with python to copy files to a remote system. I am using a very simple test example:
import os
src = "C:\<Username>\Desktop\test2.txt"
dst = "C:\Users\<Username>"
print os.system("xcopy %s %s" % (src, dst))
But for some reason when I run this I get:
Invalid number of parameters
4
Running the xcopy directly from the command line works fine. Any ideas?
Thanks
\t is a tab character. I'd suggest using raw strings for windows paths:
src = r"C:\<Username>\Desktop\test2.txt"
dst = r"C:\Users\<Username>"
This will stop python from surprising you by interpreting some of your backslashes as escape sequences.
In addition to using raw string literals, use the subprocess module instead of os.system - it will take care of quoting your arguments properly if they contain spaces. Thus:
import subprocess
src = r'C:\<Username>\Desktop\test2.txt'
dst = r'C:\Users\<Username>'
subprocess.call(['xcopy', src, dst])
Try prefixing your strings with r. So r"C:\<Username>\Desktop\test2.txt". The problem is that a backslash is treated as a special character within strings.

python and windows double backslash

I got a program running on my local machine which uses some files. I create the reference to the files by using: os.path.join( tempfile.gettempdir(), 'filename.txt' )
After that I'm running a program which accepts some parameters --log-file filepath where filepath is one of the files I just explained above.
On my machine python creates backslashes for the paths but not double backslashes and the program complains because it's considered an escape character and should be a double backslash.
Is there any standard way of making sure that I get a working path with double backslashes in python? I could use regex but I would prefer something similar to what os. provides. Maybe I'm missing something.
I'm calling the program using subprocess.Popen:
self._proc = subprocess.Popen( command.split( ' ' ) )
where command is something like pcix.exe --log-file file_path
Also, running a test on my console shows that my python does not produce double backslash for paths:
>>> print os.path.join(tempfile.gettempdir(), "test.txt")
c:\users\manilo~1\appdata\local\temp\test.txt
Leaving out the print command produces the same path:
>>> os.path.join(tempfile.gettempdir(), "test.txt")
c:\users\manilo~1\appdata\local\temp\test.txt
Any idea why?
P.S. The platform i'm running is CPython
Try:
print os.path.join(tempfile.gettempdir(), "test.txt").replace('\\\\','\\\\\\\\')

Passing empty string to argparse

I'm using argparse (Python 3.2). A parameter mode is defined simply as:
p.add_argument('--mode', dest='mode')
I want to call the program from the command line in such a way that parameter mode is set to an empty string; or at least to a single space ' ' (I can strip whitespace later).
I tried to use (under Windows) program_name --mode "" and program_name --mode " ", but neither worked.
This seems to work for me under OS-X:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--mode')
p = parser.parse_args()
print(p)
and then:
python test.py --mode=
I don't have a windows machine, so I don't know anything about how those operate...
Of course, the other things you mentioned above would work as well on OS-X. The advantage here is that it shouldn't rely on how the shell splits arguments enclosed in quotations which should make it work in more places I would think.

Categories

Resources