Make Python Subprocess Run in PowerShell
Question:
I’m trying to get the wireless debugging port of ADB in my Android, using the command here:
& "D:ToolsNmapnmap.exe" -T4 192.168.2.20 -p 37000-44000 | Where-Object {$_ -match "tcp open"} | ForEach-Object {$_.split("/")[0]}
And I would like to make a Python script for further purposes:
ip = '192.168.2.20'
nmap_path = r'D:ToolsNmapnmap.exe'
def get_port():
port_result = subprocess.run(
f'& "{nmap_path}" -T4 {ip} -p 37000-44000 | '
f'Where-Object {{$_ -match "tcp open"}} | '
f'ForEach-Object {{$_.split("/")[0]}}',
shell=True
)
port = port_result.stdout.decode('utf-8').strip()
return port
But it gave the following error: & was unexpected at this time.
, which indicated that the command was run in CMD instead of PowerShell.
I do not want to use powershell -Command
, nor saving the commands into a .ps1
file.
Could I make subprocess.run
to run specifically in PowerShell?
Answers:
The documentation says subprocess()
uses COMSPEC
to determine which shell to run if you set shell=True
.
I don’t have, want, or use Windows, but imagine you’d need something like:
import os
import subprocess
# Change COMSPEC to point to Powershell
os.putenv('COMSPEC',r'C:WindowsSystem32WindowsPowerShellv1.0powershell.exe')
subprocess.run(..., shell=True)
I’m assuming you can check that path.
I guess it would probably be good practice to save and restore the previous COMSPEC in case the change to Powershell upsets something else. So:
# Save original COMSPEC
savedCOMSPEC = os.getenv('COMSPEC')
... CODE FROM ABOVE ...
# Restore previous COMSPEC
os.putenv('COMSPEC', savedCOMSPEC)
Option 1:
You could go about this by pip-installing nmap in powershell by running powershell as administrator and running:
pip install nmap
pip install python-nmap
Then, head back to your python script, call powershell using subprocess.call followed by your path to powershell.exe, then the desired command to execute:
import subprocess
from subprocess import call
subprocess.call(f'C:WindowsSystem32powershell.exe nmap -T4 -p 37000-44000', shell=True)
OR
Option 2:
You could just import nmap as a package into your python script, still making sure that you pip-installed nmap AND python-nmap.
import nmap
scan = nmap.PortScanner()
scan.scan({ip}, '37000-44000')
I found a detailed article explaining how to do the latter method. (Importing nmap directly into your script as a package, that is.)
Best of luck and happy coding! 😉
On windows, os.environ must be used to set ‘COMSPEC’ instead of os.putenv
from subprocess import run
import os
# Change COMSPEC to point to Powershell
my_env = os.environ.copy()
my_env['COMSPEC'] = r'C:WindowsSystem32WindowsPowerShellv1.0powershell.exe'
#run process
args = [<arguments>]
p = run(args, shell=True, env = my_env)
I’m trying to get the wireless debugging port of ADB in my Android, using the command here:
& "D:ToolsNmapnmap.exe" -T4 192.168.2.20 -p 37000-44000 | Where-Object {$_ -match "tcp open"} | ForEach-Object {$_.split("/")[0]}
And I would like to make a Python script for further purposes:
ip = '192.168.2.20'
nmap_path = r'D:ToolsNmapnmap.exe'
def get_port():
port_result = subprocess.run(
f'& "{nmap_path}" -T4 {ip} -p 37000-44000 | '
f'Where-Object {{$_ -match "tcp open"}} | '
f'ForEach-Object {{$_.split("/")[0]}}',
shell=True
)
port = port_result.stdout.decode('utf-8').strip()
return port
But it gave the following error: & was unexpected at this time.
, which indicated that the command was run in CMD instead of PowerShell.
I do not want to use powershell -Command
, nor saving the commands into a .ps1
file.
Could I make subprocess.run
to run specifically in PowerShell?
The documentation says subprocess()
uses COMSPEC
to determine which shell to run if you set shell=True
.
I don’t have, want, or use Windows, but imagine you’d need something like:
import os
import subprocess
# Change COMSPEC to point to Powershell
os.putenv('COMSPEC',r'C:WindowsSystem32WindowsPowerShellv1.0powershell.exe')
subprocess.run(..., shell=True)
I’m assuming you can check that path.
I guess it would probably be good practice to save and restore the previous COMSPEC in case the change to Powershell upsets something else. So:
# Save original COMSPEC
savedCOMSPEC = os.getenv('COMSPEC')
... CODE FROM ABOVE ...
# Restore previous COMSPEC
os.putenv('COMSPEC', savedCOMSPEC)
Option 1:
You could go about this by pip-installing nmap in powershell by running powershell as administrator and running:
pip install nmap
pip install python-nmap
Then, head back to your python script, call powershell using subprocess.call followed by your path to powershell.exe, then the desired command to execute:
import subprocess
from subprocess import call
subprocess.call(f'C:WindowsSystem32powershell.exe nmap -T4 -p 37000-44000', shell=True)
OR
Option 2:
You could just import nmap as a package into your python script, still making sure that you pip-installed nmap AND python-nmap.
import nmap
scan = nmap.PortScanner()
scan.scan({ip}, '37000-44000')
I found a detailed article explaining how to do the latter method. (Importing nmap directly into your script as a package, that is.)
Best of luck and happy coding! 😉
On windows, os.environ must be used to set ‘COMSPEC’ instead of os.putenv
from subprocess import run
import os
# Change COMSPEC to point to Powershell
my_env = os.environ.copy()
my_env['COMSPEC'] = r'C:WindowsSystem32WindowsPowerShellv1.0powershell.exe'
#run process
args = [<arguments>]
p = run(args, shell=True, env = my_env)