Home > Software engineering >  Command works on Command Prompt but it does not work when called with subprocess.run() or os.system(
Command works on Command Prompt but it does not work when called with subprocess.run() or os.system(

Time:10-28

Python 3.10.6 Windows 10

I have a python function that executes a DXL script using subsystem.run() or os.system() (whichever works best I guess). The problem is that when I run a custom command using python it does not work, but when I paste the same command in the command prompt, it works. I should also clarify that command prompt is not the ms store windows terminal (cannot run ibm doors commands there for some reason). It is the OG prompt

I need to use both python and IBM Doors for the solution. Here is a summer version of my code (Obviously, the access values are not real):

    @staticmethod
    def run_dxl_importRTF():
        dquotes = chr(0x22) # ASCII --> "

        module_name = "TEST_TEMP"
        script_path = "importRTF.dxl"
        script_do_nothing_path = "doNothing.dxl"
        user = "user"
        password = "pass"
        database_config = "[email protected]"
        doors_path = dquotes   r"C:\Program Files\IBM\Rational\DOORS\9.7\bin\doors.exe"   dquotes
        file_name = "LIBC_String.rtf"
        
        # Based On: 
        # "C:\Program Files\IBM\Rational\DOORS\9.7\\bin\doors.exe" -dxl "string pModuleName = \"%~1\";string pFilename = \"%~2\";#include <importRTF.dxl>" -f "%TEMP%" -b "doNothing.dxl" -d [email protected] -user USER -password PASSWORD

        script_arguments = f"{dquotes}string pModuleName=\{dquotes}{module_name}\{dquotes};string pFileName=\{dquotes}{file_name}\{dquotes};#include <{script_path}>{dquotes}"
        command = [doors_path, "-dxl", script_arguments, "-f", "%TEMP%", "-b", script_do_nothing_path, '-d', database_config, '-user', user, '-password', password]
        
        res = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)

        print(f"COMMAND:\n{' '.join(res.args)}")
        print(f"STDERR: {repr(res.stderr)}")
        print(f'STDOUT: {res.stdout}')
        print(f'RETURN CODE: {res.returncode}')

        
        return

PYTHON SCRIPT OUTPUT:

    COMMAND:
    "C:\Program Files\IBM\Rational\DOORS\9.7\bin\doors.exe" -dxl "string pModuleName=\"TEST_TEMP\";string pFileName=\"LIBC_String.rtf\";#include <importRTF.dxl>" -f %TEMP% -b doNothing.dxl -d [email protected] -user USER_TEMP -password PASS_TEMP
    STDERR: 'The system cannot find the path specified.\n'
    STDOUT:
    RETURN CODE: 1

When I run the same command in the command prompt, it works (dxl script is compiled). I identified the problem which is the script_argument variable. Meaning that, when I try to just enter the IBM Doors server without compiling a DXL script, it works on python and the command prompt.

The python script needs to be dynamic meaning that all of the initial declared variables can change value and have a path string in it. I am also trying to avoid .bat files. They also did not work with dynamic path values

Thanks for your time

I tried:

  • Changing CurrentDirectory (cwd) to IBM Doors
  • os.system()
  • Multiple workarounds
  • Tried IBM Doors path without double quotes (it doesnt work because of the whitespaces)
  • .bat files

CodePudding user response:

When calling subprocess.run with a command list and shell=True, python will expand the command list to a string, adding more quoting along the way. The details are OS dependent (on Windows, you always have to expand the list to a command) but you can see the result via the subprocess.list2cmdline() function.

Your problem is these extra escapes. Instead of using a list, build a shell command string that already contains the escaping you want. You can also use ' for quoting strings so that internal " needed for shell quoting can be entered literally.

Putting it all together (and likely messing something up here), you would get

@staticmethod
def run_dxl_importRTF():
    module_name = "TEST_TEMP"
    script_path = "importRTF.dxl"
    script_do_nothing_path = "doNothing.dxl"
    user = "user"
    password = "pass"
    database_config = "[email protected]"
    doors_path = r"C:\Program Files\IBM\Rational\DOORS\9.7\bin\doors.exe"
    file_name = "LIBC_String.rtf"
    script_arguments = (rf'string pModuleName=\"{module_name}\";'
        'string pFileName=\"{file_name}\";'
        '#include <{script_path}>')
    command = (f'"{doors_path}" -dxl "{script_arguments}" -f "%TEMP%"'
        ' -b "{script_do_nothing_path}" -d {database_config}'
        ' -user {user} -password {pass}')
    
    res = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)

    print(f"COMMAND:\n{' '.join(res.args)}")
    print(f"STDERR: {repr(res.stderr)}")
    print(f'STDOUT: {res.stdout}')
    print(f'RETURN CODE: {res.returncode}')
  • Related