Search code examples
pythonwindowspython-2.7powershellstdout

Running powershell script within python script, how to make python print the powershell output while it is running


I am writing a python script which checks various conditions and runs a powershell script accordingly to help me automate migration from windows XP to windows 7. The powershell script gives its own output giving the user updates as to what is happening. I would like to take the output of the powershell script and print it as output of the python script. I have looked around at some questions which seem to want to do the same thing but they don't seem to be working for me. Initially I tried using

import subprocess
subprocess.call(["C:\Users\gu2124\Desktop\helloworld.ps1"])

As was suggested here Run PowerShell function from Python script but I found out that this waits for the program to execute first and does not give output so I found out I need to use subprocess.Popen() as was suggusted here Use Popen to execute a Powershell script in Python, how can I get the Powershell script's output and update it to web page? so I tried this

import subprocess
subprocess.Popen(["C:\Users\gu2124\Desktop\helloworld.ps1"], stdout=sys.stdout)

and I get this error

Traceback (most recent call last):
  File "C:\Users\gu2124\Desktop\pstest.py", line 5, in <module>
    subprocess.Popen(["C:\Users\gu2124\Desktop\helloworld.py1"], stdout=sys.stdout)
  File "C:\Python27\lib\subprocess.py", line 701, in __init__
    errread, errwrite), to_close = self._get_handles(stdin, stdout, stderr)
  File "C:\Python27\lib\subprocess.py", line 848, in _get_handles
    c2pwrite = msvcrt.get_osfhandle(stdout.fileno())
  File "<string>", line 523, in __getattr__
  File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\core\netref.py", line 150, in __getattr__
    return syncreq(self, consts.HANDLE_GETATTR, name)
  File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\core\netref.py", line 71, in syncreq
    return conn.sync_request(handler, oid, *args)
  File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\core\protocol.py", line 434, in sync_request
    raise obj

AttributeError: DebugOutput instance has no attribute 'fileno'

I'm not completely sure what this means but from what I think I understand after reading this AttributeError: StringIO instance has no attribute 'fileno' is that it is because I am messing with the stdout incorrectly. I looked a around more and I found this Why won't my python subprocess code work? where the answers said to use stdout=subprocess.PIPE so I tried this

import subprocess
subprocess.Popen(["C:\Users\gu2124\Desktop\helloworld.ps1"], stdout=subprocess.PIPE)

which also does not give me output Finally I saw this http://www.pythonforbeginners.com/os/subprocess-for-system-administrators and changed my code to this

import subprocess
p = subprocess.Popen(["powershell","C:\Users\gu2124\Desktop\helloworld.ps1"], stdout=subprocess.PIPE)
print p.communicate

I thought that it may because I am initially trying to run a powershell script from the command line so I have to open powershell first. When I type these commands directly into the command line it works the way it should but when I run it through the python script it gives this

<bound method Popen.communicate of <subprocess.Popen object at 0x00000000026E4A90>>

which is an improvement I guess but not the "Hello world" I was expecting. I have no idea what I should try to do next to get this to work. Any help would be greatly appreciated

Also if the powershell script I am using is needed here it is

$strString = "Hello World"
write-host $strString

function ftest{
$test = "Test"
write-host $test
}

EDIT: I tried upgrading to python 3.3 like was suggested in the first answer but I still can't get it to work. I used the command p = subprocess.Popen(['powershell.exe', "C:\\Users\\gu2124\\Desktop\\helloworld.ps1"], stdout=sys.stdout) and am sure the file is there but am getting this error:

Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    p = subprocess.Popen(['powershell.exe', "C:\\Users\\gu2124\\Desktop\\helloworld.ps1"], stdout=sys.stdout)
  File "C:\Python27\lib\subprocess.py", line 701, in __init__
    errread, errwrite), to_close = self._get_handles(stdin, stdout, stderr)
  File "C:\Python27\lib\subprocess.py", line 848, in _get_handles
    c2pwrite = msvcrt.get_osfhandle(stdout.fileno())
UnsupportedOperation: fileno 

Solution

    1. Make sure you can run powershell scripts (it is disabled by default). Likely you have already done this. http://technet.microsoft.com/en-us/library/ee176949.aspx

      Set-ExecutionPolicy RemoteSigned
      
    2. Run this python script on your powershell script helloworld.py:

      # -*- coding: iso-8859-1 -*-
      import subprocess, sys
      
      p = subprocess.Popen(["powershell.exe", 
                    "C:\\Users\\USER\\Desktop\\helloworld.ps1"], 
                    stdout=sys.stdout)
      p.communicate()
      

    This code is based on python3.4 (or any 3.x series interpreter), though it should work on python2.x series as well.

    C:\Users\MacEwin\Desktop>python helloworld.py
    Hello World