Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Subprocess run, check_output, Popen returns empty string when I run the script from a batch file and from Task Scheduler

Tags:

I have a batch file which is running a python script and in the python script, I have a subprocess function which is being ran.

I have tried subprocess.check_output, subprocess.run, subprocess.Popen, all of them returns me an empty string only when running it using a batch file.

If I run it manually or using an IDE, I get the response correctly. Below is the code for subprocess.run:

    response = subprocess.run(fileCommand, shell=True, cwd=pSetTableauExeDirectory, capture_output=True)
    self.writeInLog(' Command Response: \t' + str(response))

Response is in stdout=b''

When ran in batch file and from task scheduler:

Command Response: CompletedProcess(args='tableau refreshextract --config-file "Z:\XXX\tableau_config\SampleSuperStore.txt"', returncode=0, stdout=b'', stderr=b'')

When ran manually or in IDE:

Command Response: CompletedProcess(args='tableau refreshextract --config-file "Z:\XXX\tableau_config\SampleSuperStore.txt"', returncode=0, stdout=b'Data source refresh completed.\r\n0 rows uploaded.\r\n', stderr=b'')

Batch file which runs the python program. Parameters are parsed to the python application

SET config=SampleSuperStore.txt
CALL C:\XXX\AppData\Local\Continuum\anaconda3\Scripts\activate.bat
C:\XXX\AppData\Local\Continuum\anaconda3\python.exe Z:\XXX\pMainManual.py "%config%"

Why is that??

--Complete python code---

try:
    from pWrapper import wrapper
    import sys
except Exception as e:
    print(str(e))

class main:

    def __init__(self):
        self.tableauPath = 'C:\\Program Files\\Tableau\\Tableau 2018.3\\bin\\'
        self.tableauCommand = 'tableau refreshextract --config-file' 

    def runJob(self,argv): 
        self.manual_sProcess(argv[1])

    def manual_sProcess(self,tableauConfigFile):    
        new_wrapper = wrapper()
        new_wrapper.tableauSetup(self.tableauPath,self.tableauCommand)
        if new_wrapper.tableauConfigExists(tableauConfigFile):
            new_wrapper.tableauCommand(tableauConfigFile)           

if __name__ == "__main__":
    new_main = main()
    new_main.runJob(sys.argv)  

Wrapper class:

def tableauCommand(self,tableauConfigFile):    
    command = self.setTableauExeDirectory + ' ' + self.refreshConfigCommand + ' "' + tableauConfigFile + '"'
    self.new_automateTableauExtract.runCommand(tableauConfigFile,command,self.refreshConfigCommand,self.tableauFilePath,self.setTableauExeDirectory)   

Automate Class:

def runCommand(self,pConfig,pCommand,pRefreshConfigCommand,pFilePath,pSetTableauExeDirectory):
    try:
        fileCommand = pRefreshConfigCommand + ' "' + pFilePath + '"'
        response = subprocess.run(fileCommand, shell=True, cwd=pSetTableauExeDirectory, capture_output=True)
        self.writeInLog(' Command Response: \t' + str(response))
    except Exception as e:
        self.writeInLog('Exception in function runCommand: ' + str(e))

UPDATE: I initially thought that the bat file was causing this issue but it looks like it works when running manually a batch file but not when it is set on task scheduler

like image 876
Jonathan Lam Avatar asked Dec 02 '19 21:12

Jonathan Lam


People also ask

What is the output of subprocess Check_output?

The subprocess. check_output() is used to get the output of the calling program in python. It has 5 arguments; args, stdin, stderr, shell, universal_newlines. The args argument holds the commands that are to be passed as a string.

What does the popen () return on success?

If successful, popen() returns a pointer to an open stream that can be used to read or write to a pipe. If unsuccessful, popen() returns a NULL pointer and sets errno to one of the following values: Error Code. Description.

What is Popen in subprocess?

The subprocess module defines one class, Popen and a few wrapper functions that use that class. The constructor for Popen takes arguments to set up the new process so the parent can communicate with it via pipes. It provides all of the functionality of the other modules and functions it replaces, and more.

What is the difference between subprocess run and Popen?

The main difference is that subprocess. run() executes a command and waits for it to finish, while with subprocess. Popen you can continue doing your stuff while the process finishes and then just repeatedly call Popen. communicate() yourself to pass and receive data to your process.


1 Answers

Updated

First of all, if there is a need to run anaconda-prompt by calling activate.bat file, you can simply do as follows:

import subprocess


def call_anaconda_venv():
    subprocess.call('python -m venv virtual.env')
    subprocess.call('cmd.exe /k /path/venv/Scripts/activate.bat')


if __name__ == "__main__":
    call_anaconda_venv()
  • The result of the above code would be a running instance of anaconda-prompt as required.

Now as Problem Seems Like:


I have a batch file which is running a python script and in the python script, I have a subprocess function which is being run.

I have implemented the same program as required; Suppose we have

  • Batch File ---> script.bat **** includes a command to run python script i.e test.py. ****

  • Python Script File ---> test.py **** includes a method to run commands using subprocess. ****

  • Batch File ---> sys_info.bat **** includes a command which would give the system information of my computer. ****


Now First, script.bat includes a command that will run the required python script as given below;

python \file_path\test.py 
pause

Here, pause command is used to prevent auto-closing console after execution. Now we have test.py, python script which includes subprocess method to run required commands and get their output.


from subprocess import check_output


class BatchCommands:

    @staticmethod
    def run_commands_using_subprocess(commands):
        print("Running commands from File: {}".format(commands))
        value = check_output(commands, shell=True).decode()

        return value

    @staticmethod
    def run():
        commands_from_file = "\file-path\sys_info.bat"

        print('##############################################################')
        print("Shell Commands using >>> subprocess-module  <<<")
        print('##############################################################')

        values = BatchCommands.run_commands_using_subprocess(commands_from_file)
        print(values)


if __name__ == '__main__':
    BatchCommands.run()

Now, in the end, I have a sys_info.bat file which includes commands to renew the IP-Adress of my computer. Commands in sys_info.bat file are as follows;

systeminfo

Place multiple commands in sys_info.bat file, then you can also run multiple commands at a time like:

ipconfig/all
ipconfig/release
ipconfig/reset
ipconfig/renew
ipconfig

Before to use the file, set all files directory paths, and run the batch file i.e script.py in command-prompt as follows;

  • Run command-prompt or terminal as an administrator.

     run \file_path\script.py
    

Here is the result after running the batch file in the terminal.

Output of Given Batch File using Task Schedular which runs a sub-process method.

like image 135
Muhammad Usman Bashir Avatar answered Oct 18 '22 12:10

Muhammad Usman Bashir