-2

I am in the same situation as the person who asked this question and at the same time he managed to answer it using "win32(something)" instead of "subprocess": how to open a cmd shell in windows and issue commands to that shell using python

I am partially satisfied with this answer, but I have encountered a new problem: How do I "capture" the outputs (strings) generated by each command line (or at least the last command line used)?

To give you a more contextual idea, I use a program that requires command lines in cmd.exe (imagemagick), I use it to compare images and, using a complex statistical criterion, I obtain a floating number between 0 and 1.

Precisely that number is the one I want to capture.

Explicit example.

This is my current code:

import time 

import os from win32com import client from win32gui import GetWindowText, GetForegroundWindow, SetForegroundWindow, EnumWindows from win32process import GetWindowThreadProcessId

class ActivateVenv:

def set_cmd_to_foreground(self, hwnd, extra): """sets first command prompt to forgeround""" if "cmd.exe" in GetWindowText(hwnd): SetForegroundWindow(hwnd) return def get_pid(self): """gets process id of command prompt on foreground""" window = GetForegroundWindow() return GetWindowThreadProcessId(window)[1] def activate_venv(self, shell, venv_location): """activates venv of the active command prompt""" shell.AppActivate(self.get_pid()) #shell.SendKeys("cd \ {ENTER}") #shell.SendKeys(r"cd %s {ENTER}" % venv_location) #shell.SendKeys("activate {ENTER}") def run_py_script(self,shell): """runs the py script""" shell.SendKeys("cd ../..{ENTER}") shell.SendKeys("python run.py {ENTER}") def run_script(self,shell,command_line): """runs a general script""" shell.SendKeys(command_line) def open_cmd(self, shell): """ opens cmd """ shell.run("cmd.exe") time.sleep(1) def comparar(p,q): try: return 'magick compare -metric ncc C:\GTSgiffer\INput\{}.png C:\GTSgiffer\INput\{}.png null: 2>&1'.format(p,q) except: print(f"Error en comparar({p},{q})") pass if __name__ == "__main__": '''shell = client.Dispatch("WScript.Shell") run_venv = ActivateVenv() run_venv.open_cmd(shell) EnumWindows(run_venv.set_cmd_to_foreground, None) run_venv.activate_venv(shell, "flask3.5/venv/scripts") run_venv.run_py_script(shell)''' shell = client.Dispatch("WScript.Shell") run_venv = ActivateVenv() run_venv.open_cmd(shell) EnumWindows(run_venv.set_cmd_to_foreground, None) run_venv.activate_venv(shell, "flask3.5/venv/scripts") run_venv.run_script(shell,r"cd C:\GTSgiffer\bin {ENTER}") run_venv.run_script(shell,comparar(1,2)+" {ENTER}") run_venv.run_script(shell,comparar(1,3)+" {ENTER}") 
4
  • 1
    Is there a reason you don't want to use subprocess? Commented Jul 1, 2020 at 17:39
  • Hello @FARS, Welcome to Stack Overflow! Please copy and paste your code/command and its desired output directly into the post instead of linking to an animated gif. Commented Jul 1, 2020 at 18:01
  • To Paul M.: I would likt to use "subprocess", but I don't how how to send a command line from a Python script to a open cmd.exe window without closing that window. I use win32(somthing) because that was the only solution that it workd to me. Commented Jul 1, 2020 at 18:09
  • To Yatin: It's a very long code from my script, but the main idea is the same from this old question: stackoverflow.com/questions/33059905/… Commented Jul 1, 2020 at 18:14

1 Answer 1

0
>>> from subprocess import run >>> result = run("magick compare -metric ncc 1.jpg 2.jpg null:", capture_output=True) >>> result CompletedProcess(args='magick compare -metric ncc 1.jpg 2.jpg null:', returncode=1, stdout=b'', stderr=b'0.25404') >>> result.stderr b'0.25404' 

Try using the run function introduced in Python 3.5. Its the recommended way to invoke a process.

subprocess run

You can also use the following, but its not required.

result = run("cmd.exe /c magick compare -metric ncc 1.jpg 2.jpg null:", capture_output=True) 
Sign up to request clarification or add additional context in comments.

5 Comments

Basically, what I want is, from an already open cmd.exe window, to send a command and then get its result, but without closing that same cmd.exe window. Repeatedly send several commands to the same cmd.exe window, because I want to get many numerical results to process several images.
The answer you gave me I already knew, but the bad thing is that it closes the cmd.exe window once the sent command line is over.
ok, I might have read it wrong, you said in your original post that you need to capture the number. Anyways, since you posted your code post my comment. I must have missed your code. It makes more sense now.
@FARS just use result = run("cmd.exe /k magick compare -metric ncc 1.jpg 2.jpg null:", capture_output=True) instead to keep it open?
To Neko Musume: I want to keep open the cmd.exe because I want to send a command to delete file later: "del something.png". I tried before to work with ephemeral windows (which open, execute a command, and then close), but this gives me an error in the long run and fails to store the float numbers (the outputs I want to keep).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.