4

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

Jonathan Lam
  • 1,237
  • 3
  • 20
  • 49
  • We need way more of your code to help. The batch and python files, to start. – artemis Dec 04 '19 at 22:53
  • Posted the batch and python – Jonathan Lam Dec 04 '19 at 23:01
  • Very likely culprit is the "shell=True" on Windows. IDE and batch are prob. using different shell, or using the quotes differently. Instead of using shell=True, first, construct the argv for subprocess so that you know exactly what your command arguments are. That includes your tableauCommand part too. One way to debug this as is, is to swap the command to "echo" and see the command it is generating. – Naoyuki Tai Dec 06 '19 at 03:47

2 Answers2

4

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.

Muhammad Usman Bashir
  • 1,441
  • 2
  • 14
  • 43
  • 1
    Hmm I need to check that. I am using Anaconda Prompt to run the python script and I can see that you are using python from cmd prompt itself – Jonathan Lam Dec 10 '19 at 02:06
  • 5
    For me it worked for **both** `windows commands prompt` as well as `anaconda command prompt`. You can run anaconda command prompt with or without admin privileges. Even if, I run another python script which is running `script.bat` using **os.system()**. It worked ! The thing is **files paths** must be specified. You will get the required output, if run properly. – Muhammad Usman Bashir Dec 10 '19 at 07:13
  • 1
    Did you call the activate.bat to run anaconda prompt? CALL C:\XXX\AppData\Local\Continuum\anaconda3\Scripts\activate.bat – Jonathan Lam Dec 10 '19 at 17:56
  • 1
    Yes, I have use `call \path\activate.bat` command to run my **anaconda-(venv)**. Have a look on the answer, i have also added code to run (venv) using `subprocess.call`. – Muhammad Usman Bashir Dec 10 '19 at 20:50
  • I have checked it. I have noticed that the issue of empty string is raised when running from task scheduler. I initially thought that it was the batch file causing it. Can you try to enter the batch file in task scheduler and see if you get a response when running it from there? – Jonathan Lam Dec 12 '19 at 16:05
  • 2
    @Jonathan, Sorry for being late. I have easily managed to run the batch file using `Task Scheduler`, The only thing is that you have to give the **full Specified Path** of each file used in your program, whether they are in the same directory. Secondly, kindly add `pause` command in script.bat file, it will give the record output. For me, it worked. I have updated the answer kindly revisit. – Muhammad Usman Bashir Dec 17 '19 at 10:53
0

This is happening because your ide is not running in a shell that works in the way that open subprocess is expecting.

If you set SHELL=False and specify the absolute path to the batch file it will run.

you might still need the cwd if the batch file requires it.

Amias
  • 335
  • 6
  • 16