1

I am trying to get my basic python script to open and to write to and read to a cmd in order to allow it to send commands into noxplayer. I am trying to use sub processes and have discovered and read about using PIPES and not using them. Either way I can get it to send input with it resulting in a series of different breakpoints. Here are 2 examples of code I have tried.

class bot:
    def __init__(self, num):
        self.num = num

    def start(self):
        #open app and command prompt
        androidArg1 = "C:/Program Files (x86)/Nox/bin/Nox.exe"
        androidArg2 = "-clone:Nox_" + str(self.num)
        androidArgs = [androidArg1, androidArg2]
        cmdArg1 = 'cmd'
        cmdArgs = [cmdArg1]
        self.app = subprocess.Popen(androidArgs)
        self.cmd = subprocess.Popen(cmdArgs, shell=True)

        self.cmd.communicate(input="cd C:/Program Files (x86)/Nox/bin")
        while True:
            self.devices = self.cmd.communicate(input="nox_adb devices")
            print(self.devices)

is printing out C:\Users\thePath> but never finishes the first communication

class bot:
    def __init__(self, num):
        self.num = num

    def start(self):
        #open app and command prompt
        androidArg1 = "C:/Program Files (x86)/Nox/bin/Nox.exe"
        androidArg2 = "-clone:Nox_" + str(self.num)
        androidArgs = [androidArg1, androidArg2]
        cmdArg1 = 'cmd'
        cmdArgs = [cmdArg1]
        self.app = subprocess.Popen(androidArgs)
        self.cmd = subprocess.Popen(cmdArgs, stdin=PIPE, stderr=PIPE, stdout=PIPE, universal_newlines=True, shell=True)
        stdout, stderr = self.cmd.communicate()
        stdout, stderr


        self.cmd.communicate(input="cd C:/Program Files (x86)/Nox/bin")
        while True:
            self.devices = self.cmd.communicate(input="nox_adb devices")
            print(self.devices)

throws

Cannot send input after starting communication

What am I doing wrong and what is the right way to go about doing this?

1 Answer 1

3

communicate is great because it is able to read standard output and error separately.

But otherwise it's pretty clunky as it sends the input only once. So as soon as this happens:

stdout, stderr = self.cmd.communicate()

it's over, you cannot send more input to your process.

Another way would be:

  • feed input line by line to the process
  • merge standard output and error (to avoid deadlocks)

but here it would be overkill. What's overkill in the first place is to Popen on a Windows cmd process when you don't need it at all. plus the cd command, plus the input feed, plus the shell=True ...

make it simple

Instead, use Popen directly on the nox command in the loop (with a small delay in between the calls maybe).

I didn't test that, but this is a self-contained way to running a command with an argument, in a given directory, repeatedly, and read its output.

import time,subprocess
while True:
    p = subprocess.Popen(["nox_adb","devices"],cwd="C:/Program Files (x86)/Nox/bin",stdout=subprocess.PIPE)
    devices = p.stdout.read().decode()
    rc = p.wait()   # wait for process to end & get return code
    if rc:
       break  # optional: exit if nox_adb command fails
    time.sleep(1)

if nox_adb is a .bat file that isn't going to cut it, in which case prefix the command by cmd /c:

    p = subprocess.Popen(["cmd","/c","nox_adb","devices"],cwd="C:/Program Files (x86)/Nox/bin",stdout=subprocess.PIPE)

this is roughly equivalent to adding shell=True on Windows, but shell=True is a lazy way of solving an issue that comes back in your head like a boomerang years later so better avoid it in industrial solutions.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you I was defiantly overthinking it. The code you provided p = subprocess.Popen(["nox_adb","devices"],cwd="C:/Program Files (x86)/Nox/bin",stdout=subprocess.PIPE) is throwing can't find file so I changed it to subprocess.Popen(['cmd', "nox_adb", "devices"], cwd="C:/Program Files (x86)/Nox/bin", stdout=subprocess.PIPE) and that is working but gets stuck on p.stdout.read().decode() and never moves on to the next line of code.
nox_adb is probably a .bat file. In which case just use shell=True instead of cmd else the command never ends. or ["cmd","/c","nox_adb.bat","devices"] without shell=True is even better

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.