subprocess.call vs os.system python - python

First time questioning here:
I have a need to map a network drive in windows. The location is an internal sharepoint document library.
In the cmd window:
net use g: http://na.com/DMP/DMP/programming/
is successfull --> the command completed succeffuly
os.system('"net use k: http://na.com/DMP/DMP/programming/"')
is also successful.
However i would like to use subprocess.call in the event that the drive is already mapped - i would like to try another drive
call(["net", "use", ":q", '"http://na.com/DMP/DMP/programming/"'])
This fails with "System error 67 has occured. The network name cannot be found"
I have tried many options for the last list item with no luck.
Any idea what I can stuff in there to have this complete successfully or a different method to map drives.

There are at least two problems in your code:
call(["net", "use", ":q", '"http://na.com/DMP/DMP/programming/"'])
First, you've got ":q" where you meant "q:". This might cause the net command to interpret :q as your network location instead of your target drive, which could cause an error 67.
Second, you've got an extra set of quotes around the URL: '"http://na.com/DMP/DMP/programming/"' where you should be using 'http://na.com/DMP/DMP/programming/'. When subprocess builds the string to pass to CreateProcess, it already quotes each of your parameters. So, if you quote them yourself, you end up double-quoting the parameters. There are some cases where this is actually not possible in Windows, so you end up with garbage, but I don't think that's the case here. You will successfully get this quoted string to net, telling it that you want to open either a relative path starting with "http: or a URL with protocol "http, or something like that. Whatever it is, it's not a usable network location, which most likely will cause an error 67.
As Ben pointed out, your system call has a similar problem—you put an extra pair of quotes around the entire string. If you really wanted to figure it out, there probably is some reason that this worked… but I don't think you want to figure it out. Just take it as "I did the wrong thing, but I got lucky", and don't do it that way in the future.
Finally, as the documentation says:
On Windows, an args sequence is converted to a string that can be parsed
This means that, if you already have a working command line for Windows, you're better off just using it as a string, than trying to break it down into a sequence for subprocess to reassemble.
(Keep in mind that this is only true for Windows! On other platforms, instead of building a command line string to pass to a function in the CreateProcess family, subprocess builds an array of strings to pass to a function in the exec family.)
So, just do this:
call("net use g: http://na.com/DMP/DMP/programming/")

Related

Line terminator adds dot at the end of a line in npm test of Python code

I wanted to learn command line programming using Python.
I saw a to-do challenge on the internet and started to work on it by learning from the web. The challenge is to create a command line interface of a to-do app.
The challenge is titled CoronaSafe Engineering Fellowship Test Problem. Here is the challenge material on Google Drive: https://drive.google.com/drive/folders/1SyLcxnEBNRecIyFAuL5kZqSg8Dw4xnTG?usp=sharing
and there is a GitHub project at https://github.com/nseadlc-2020/package-todo-cli-task/
In the README.md I was instructed to create symbolic link for the batch file todo.bat with the name todo. Now, my first condition is that, when the symbolic link is called from the command prompt without any arguments, it must print some usage tips for the program. Finally, I have to use the npm test command to test the execution.
At the very beginning I got this trouble, whenever I use a print statement, I see a dot • at the end of every string which ends with a new line. For instance,
import sys
import random
args = sys.argv[1:]
if len(args) == 0:
print('Usage :-', end='\n')
print('$ ./todo help # Show usage', end='')
The above statements when executed without arguments gives the output,
Usage :-.
$ ./todo help # Show usage
Here, I noticed that for the first print statement ends with a newline, the string ends with what looks like a middle dot (•). Whereas, for the second print statement since I override the end parameter with an empty string, no newline character was output, and so the dot is not printed. See the screen shot:
What's wrong, and how can I pass the test? My program does not print a middle dot at all.
The problem seems to be squarely inside the todo.test.js file.
In brief, Windows and Unix-like platforms have different line ending conventions (printing a line in Windows adds two control characters at the end, whilst on Unix-like systems only one is printed) and it looks like the test suite is only prepared to cope with results from Unix-like systems.
Try forcing your Python to only print Unix line feeds, or switch to a free Unix-like system for running the tests.
Alternatively, rename todo.test.js and replace it with a copy with DOS line feeds. In many Windows text editors, you should be able to simply open the file as a Unix text file, then "Save As..." and select Windows text file (maybe select "ANSI" if it offers that, though the term is horribly wrong and they should know better); see e.g. Windows command to convert Unix line endings? for many alternative solutions (many of which vividly illustrate some of the other issues with Windows; proceed with caution).
This seems to be a known issue, as noted in the README.md you shared: https://github.com/nseadlc-2020/package-todo-cli-task/issues/12 (though it imprecisely labels this as "newline UTF encoding issues"; the problem has nothing to do with UTF-8 or UTF-16).
See also the proposed duplicate Line endings (also known as Newlines) in JS strings
I had exactly the same problem.
I replaced:
print(variable_name) # Or print("Your text here")
With:
sys.stdout.buffer.write(variable_name.encode('utf-8')) # To sys.stdout.buffer.write("Your text here".encode('utf-8'))
Now it worked fine in windows.
First write your help string like this
help_string='Usage :-\n$ ./task add 2 hello world # Add a new item with priority 2 and text "hello world" to the list\n$ ./task ls # Show incomplete priority list items sorted by priority in ascending order\n$ ./task del INDEX # Delete the incomplete item with the given index\n$ ./task done INDEX # Mark the incomplete item with the given index as complete\n$ ./task help # Show usage\n$ ./task report # Statistics'
Then print it on the console using
sys.stdout.buffer.write(help_string.encode('utf8'))
This problem occurs due to differences in encoding type of windows and npm tests. Also make sure to avoid any spaces after or before "\n".
Why have multiple prints,when python prints can incorporate new line without having to declare separately, follow example below:
print("Usage :- \n$ ./todo help #Show usage")
Output:
Usage :-
$ ./todo help #Show usage

How do I parse the output of getmac command?

After doing some research I found out that the best way to get the Ethernet MAC address under windows is the "getmac" command. (getmac module of python does not produce the same!!). Now I want to use this command from within a python code to get the MAC address. I figured out that my code should start something like this:
import os
if sys.platform == 'win32':
os.system("getmac")
do something here to get the first mac address that appears in the results
here is an example output
Physical Address Transport Name
=================== ==========================================================
1C-69-7A-3A-E3-40 Media disconnected
54-8D-5A-CE-21-1A \Device\Tcpip_{82B01094-C274-418F-AB0A-BC4F3660D6B4}
I finally want to get 1C-69-7A-3A-E3-40 preferably without the dashes.
Thanks in advance.
Two things. First of all, I recommend you find ways of getting the mac address more elegantly. This question's answer seems to use the uuid module, which is perhaps a good cross-platform solution.
Having said that, if you want to proceed with parsing the output of a system call, I recommend the use of Python's subprocess module. For example:
import subprocess
output_of_command = subprocess.check_output("getmac")
This will run getmac and the output of that command will go into a variable. From there, you can parse the string.
Here's how you might extract the mac address from that string:
# I'm setting this directly to provide a clear example of the parsing, separate
# from the first part of this answer.
my_string = """Physical Address Transport Name
=================== ==========================================================
1C-69-7A-3A-E3-40 Media disconnected
54-8D-5A-CE-21-1A \Device\Tcpip_{82B01094-C274-418F-AB0A-BC4F3660D6B4}"""
my_mac_address = my_string.rsplit('=', 1)[-1].split(None, 1)[0]
The first split is a right split. It's breaking up the string by the '=' character, once, starting from the end of the string. Then, I'm splitting the output of that by whitespace, limiting to one split, and taking the first string value.
Again, however, I would discourage this approach to getting a mac address. Parsing the human-readable output of command line scripts is seldom advisable because the output can unexpectedly be different than what your script is expecting. You can assuredly get the mac address in a more robust way.

Using Popen in Python to execute bat script with variable

I have a python script that is calling a bat script called testrunner.bat which in turns executes a TestSuite in SOAPUI. I actually have gotten the external call to work just fine with the following command:
Popen("testrunner.bat -s\"CCT000 - Deploy Software Release\" -R\"TestSuite Report\" -E\"Default environment\" -Ppath.packages.sq=Y:\\NIGHTLY C:\\CI\\HEDeployment\\CI-XXX-DeploySwRelease")
However, I need to be able to have the software "level" to be dynamic and need to pass the variable level into the command in place of "NIGHTLY" so I can specify if it's nightly software, or stable, etc. I have seen that I should break all the arguments up separately, but I am having a hard time.
subprocess.Popen() can take a list of arguments as well as a string. So, this should work for you:
release_type = "NIGHTLY"
Popen(['testrunner.bat',
'-s"CCT000 - Deploy Software Release"',
'-R"TestSuite Report"',
'-E"Default environment"',
'-Ppath.packages.sq=Y:' + release_type,
'C:CIHEDeploymentCI-XXX-DeploySwRelease'])
As mentioned in the docs, shlex.split can be very useful for splitting your original command string into pieces. However, at least in my case, I had to re-add the double quotes.
Also, recall that single-quoted strings can contain double quotes, and vice versa, so you don't need to escape the quotes here.

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'])

Program error while using python subprocess.call() function

I'm trying to open a program while I'm in a python script using the subprocess.call() function, It opens the program but for some reason the program doesn't allows that and just throw an "Unhandaled exception" error, I know the problem is probably in the program so there may be any other command that will open a program, fill some fields and press "Submit?"
Thanks!
Edit: I've no code to post..
str = 'd:\Softwares\X.exe'
subprocess.call(str)
I've also tried with:
subprocess.call(str,shell=True)
Try calling another program the same way. If the problem persists, the problem is with your code. If it goes away, the problem is with the program.
I think changing to 'D:/Softwares/X.exe' or one of the other string formats will help because the '\' character is the escape character ... used for example to denote a new line '\n'.
It probably works if you use forward-slashes (backslashes are escape symbols in Python). If it doesn't, write the first line like this:
str = r'd:\Softwares\X.exe'
The r tells Python that you are creating a raw string, so it will ignore escape symbols. More information at: https://docs.python.org/2/reference/lexical_analysis.html#string-literals

Categories