0

There is already a thread open on Sending arguments from Batch file to Python script. And this is working fine.

However, there seems to be an issue with returning an argument value back from that Python script.

I am calling my Python script with two parameters. The first is a string and the second is an environment variable %project_name% that has been initialized with string hello.

The Python script processes the input string sys.argv[1] and extracts the substring from beyond the final \ in the string. This substring is then copied into sys.argv[2] and then should be the new value of variable %project_name%.

However, when I run this first from Windows command line, everything works okay except that the updated sys.argv[2] is not passed back to %project_name%.

See the commands below executed in a command prompt window:

set project_name=hello

echo "%project_name%"
"hello"

"C:\python27\python" GetProject.py "#p=/Product Delivery/Product Delivery.pj#s=Team Projects/Team Projects.pj#s=Platform Pack/Platform Pack.pj#s=GERAN SAT(A)/project.pj" %project_name%
Extracting project
project.pj
Returning project
project.pj

echo "%project_name%"
"hello"

My Python script is:

import os, sys
stext = sys.argv[1]
startpos = stext.rindex("/") # get the final "/" character in the input    string
rtext = stext[startpos+1:]  # extracty the substring after this delimiter 
print "Extracting project "
print rtext
sys.argv[2] = rtext  # return this to the calling program
print "Returning project "
print sys.argv[2]

What I'm doing wrong here?

Community
  • 1
  • 1
Sproggit
  • 71
  • 1
  • 7

1 Answers1

1

There is no need to use a Python script for getting from a string the substring between last / and end of string or between last / and last period. This can be done using for example command FOR.

Example to demonstrate this feature of command processor:

The batch file is:

@echo off
if "%~1" == "" goto :EOF
for %%I in ("%~1") do set "project_name=%%~nI"
echo Project name is: %project_name%

The batch file above is called with parameter:

"#p=/Product Delivery/Product Delivery.pj#s=Team Projects/Team Projects.p j#s=Platform Pack/Platform Pack.pj#s=GERAN SAT(A)/My Project.pj"

The output is:

Project name is: My Project

Using %%~nxI instead of %%~nI in batch file results in output:

Project name is: My Project.pj

This works as command processor interprets / like \ in a file/folder string for compatibility with Unix paths.

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • call /?
  • for /?

On help output for those two commands the special codes %~1, %%~nxI and %%~nI are explained which are designed for file and folder names. But %%~nxI and %%~nI work also for any other string if the command processor does not need to find out where the file/folder with the given string is stored because there is at least one backslash or forward slash and one period after last / or \ in string.

Well, the batch file could be also:

@echo off
if "%~1" == "" goto :EOF
set "project_name=%~n1"
echo Project name is: %project_name%

But I want to answer also your question and explain why your approach can't work at all.

Command processor cmd.exe expands %project_name% to its value hello before running Python. The Python script gets passed from command processor the string hello and not the name of the environment variable.

The string hello is stored in a memory block allocated by Windows from entire RAM for the called Python interpreter. Also allocated in this memory block is an array of 3 pointers pointing to the 3 argument strings in memory.

I'm not a Python expert, but the line sys.argv[2] = rtext most likely results in deallocating the memory used for string hello and assigning address of string variable rtext to third pointer in pointer array sys.argv.

This string memory and pointer management has of course no effect on environment table of the command processor hold in RAM on a completely different address.

Working would be to print the determined string to device stdout which is redirected by command processor and the string written to the device stdout is assigned to the environment variable project_name.

Python script GetProject.py is:

import os, sys
stext = sys.argv[1]
startpos = stext.rindex("/") # get the final "/" character in the input string
rtext = stext[startpos+1:]   # extract the substring after this delimiter 
print rtext                  # output string to device stdout

And this Python script is called from batch file with:

for /F "delims=" %%I in ('C:\python27\python.exe GetProject.py "#p=/Product Delivery/Product Delivery.pj#s=Team Projects/Team Projects.p j#s=Platform Pack/Platform Pack.pj#s=GERAN SAT(A)/project.pj"') do set "project_name=%%I"

But using a Python script for getting name of project file with or without file extension is definitely not necessary.

Mofi
  • 46,139
  • 17
  • 80
  • 143
  • Hi, MofiMany thanks - this works perfectly. I had tried looking up on Google how to handle substrings in DOS, but obviously did not look in the right place. THis – Sproggit Dec 18 '15 at 12:12
  • Sorry finger trouble - sent my reply prematurely. i meant to also state that this help has been very useful as we use a lot of DOS batch files in our build process. Once again many thanks – Sproggit Dec 18 '15 at 12:14