So as the title says, I'm having problem starting a new subprocess under Fedora. Now the situation is, I have a main python script from which I start a couple of other python processes using:
import subprocess
subprocess.Popen(['python', '-m', 'first_child.run', 'start'], shell=False)
Now this works fine on MacOS, debian and windows. On fedora if I run it from Aptana 3 IDE it also works, the only problem is when i try to run this main scrip from a terminal, where I get:
OSError: [Errno 2] No such file or directory
Do you have any ideea what can be the problem here?
Regards,
Bogdan
Sorry if this is something you've already thought of -- but the most common cause of OSError from calls to subprocess is that it cannot find the process
http://docs.python.org/library/subprocess.html#exceptions
Are you absolutely certain python is in your path?
I know you're probably going to point out you ran this script from the python executable -- but I thought I'd take a shot that perhaps you specified the full path to python when you ran it from the terminal.
For fun, right before the call to subprocess, you could dump your PATH
import os
print os.environ['PATH']
It's your current working directory. I don't think the problem is that it can't find python, the problem is that it can't find first_child.run.
Try printing os.getcwd() before you launch the subprocess, and see if it's different in the terminal vs. in the IDE.
On a side note, it's probably more reliable to use sys.executable as the python you use in your subprocess, as opposed to just saying python. For example, subprocess.Popen([sys.executable, '-m', 'first_child.run', 'start'], shell=False)
Related
So I want to run a PS script that I have in my Python code, I just found this article: https://data-geek.medium.com/running-powershell-script-with-python-53a908da7d34
Since I'm using MacOS, it I changed it:
import subprocess, sys
p = subprocess.Popen(["powershell.app",
"/Users/myuser/Downloads/powershellscript.ps"],
stdout=sys.stdout)
p.communicate()
I've got an error, I guess the problem is with powershell.app .
How can I execute this PS script from my Python code?
instead of using "powershell.app" you want to use "pwsh". This is the command the starts up powershell
I'm working on using the subprocess module to send shell commands from Python, specifically, ssh. Below is a barebones sample:
import subprocess
sp = subprocess.run(["ssh"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print(f"stdout: {sp.stdout.decode()} \n\nstderr: {sp.stderr.decode()}")
This should return the ssh command help from stdout, and nothing from stderr. However, I get:
stdout:
stderr: 'ssh' is not recognized as an internal or external command,
operable program or batch file.
I've tried other commands, like echo and cd, and those work fine. I am also able to use ssh when manually typing the command into the shell, but it fails when I try to do it through subprocess. The directory C:\Windows\System32\OpenSSH does exist on my computer (and it contains ssh.exe), but for some strange reason I'm unable to cd to it using subprocess.
If it matters, subprocess is using the command prompt, cmd.exe, as it seems to be the default.
Any help is appreciated. Thanks!
-- Edits with tests from comments --
Using the absolute path C:/Windows/System32/OpenSSH/ssh.exe does not work, and gives The system cannot find the path specified via stderr. The OpenSSH folder doesn't seem to be visible to Python through subprocess
os.environ[PATH] contains both C:/Windows/System32/ and C:/Windows/System32/OpenSSH/
Running it with shell=False (either with the absolute path or just with ssh) raises an error in Python: FileNotFoundError: [WinError 2] The system cannot find the file specified
You say C:\Windows\System32\OpenSSH\ssh.exe exists, but that it's not found when running from Python. This is likely a result of having a 32 bit version of Python installed, rather than a 64 bit version.
If the path exists elsewhere, but not for Python, that would tend to implicate the file system redirector. Python is probably seeing C:\Windows\SysWOW64 when you tell it to look in C:\Windows\System32. I'd recommend uninstalling whatever Python you have, and explicitly installing a 64 bit version, so it isn't affected by the redirector, and sees the "real" System32.
I have been having some problems with subprocess.call(), subprocess.run(), subprocess.Popen(), os.system(), (and other functions to run command prompt commands) as I can't seem to get the msg command to work.
import subprocess
subprocess.call("msg * Hey",shell=True)
In theory, this should send "Hey" to every computer on the network unfortunately, this isn't running at all and I'm not quite sure why. I can run it on cmd successfully, but can't get it to work from Python.
I'd love to hear why this doesn't work and hopeful a way to fix my code or an alternate solution.
Edit: Solved, thanks for everyone's help. Upgrading to 64-bit Python did the trick.
In 64-bit Windows, "msg.exe" is only distributed as a native 64-bit binary. This file won't be found if you're using 32-bit Python, which executes under WOW64 emulation. WOW64 redirects "System32" access to the "SysWOW64" directory. In Windows 7+, use the virtual "SysNative" directory to access the real "System32". For example:
sysroot = os.environ['SystemRoot']
sysnative = os.path.join(sysroot, 'SysNative')
if not os.path.exists(sysnative):
sysnative = os.path.join(sysroot, 'System32')
msgexe_path = os.path.join(sysnative, 'msg.exe')
subprocess.call([msgexe_path, '*', 'Hey'])
Note that msg.exe has nothing to do with CMD, so there's no reason to use shell=True.
Try calling it as separate arguments:
subprocess.call(['msg', '*', 'Hey'], shell=True)
Try putting the complete path of the msg command. Example as listed
import subprocess
subprocess.call("/usr/local/bin/msg * Hey",shell=True)
I am getting the following error:
WindowsError: [Error 2] The system cannot find the file specified
My code is:
subprocess.call(["<<executable file found in PATH>>"])
Windows 7, 64 bit. Python 3.x latest, stable.
Any ideas?
Thanks,
When the command is a shell built-in, add a shell=True to the call.
E.g. for dir you would type:
import subprocess
subprocess.call('dir', shell=True)
To quote from the documentation:
The only time you need to specify shell=True on Windows is when the command you wish to execute is built into the shell (e.g. dir or copy). You do not need shell=True to run a batch file or console-based executable.
On Windows, I believe the subprocess module doesn't look in the PATH unless you pass shell=True because it use CreateProcess() behind the scenes. However, shell=True can be a security risk if you're passing arguments that may come from outside your program. To make subprocess nonetheless able to find the correct executable, you can use shutil.which. Suppose the executable in your PATH is named frob:
subprocess.call([shutil.which('frob'), arg1, arg2])
(This works on Python 3.3 and above.)
On Windows you have to call through cmd.exe. As Apalala mentioned, Windows commands are implemented in cmd.exe not as separate executables.
e.g.
subprocess.call(['cmd', '/c', 'dir'])
/c tells cmd to run the follow command
This is safer than using shell=True, which allows shell injections.
If you are using powershell, then in it will be subprocess.call(['powershell','-command','dir']). Powershell supports a large portion of POSIX commands
After much head scratching, I discovered that running a file that is located in C:\Windows\System32\ while running a 32bit version of python on a 64bit machine is a potential issue, due to Windows trying to out-smart the process, and redirect calls to C:\Windows\System32 to C:\Windows\SysWOW64.
I found an example of how to fix this here:
http://code.activestate.com/recipes/578035-disable-file-system-redirector/
To quote from the documentation:
"Prior to Python 3.5, these three functions comprised the high level API to subprocess. You can now use run() in many cases, but lots of existing code calls these functions."
SO: instead of subprocess.call use subprocess.run for Python 3.5 and above
I met the same issue while I was calling a PHP. The reason is PHP isn't in PATH so the command PHP was not found. But PowerShell found it does exist in the current location and it suggests replacing the 'PHP' by the '.\PHP' if I trust this command. Then it runs well.
I'm working in a windows environment (my laptop!) and I need a couple of scripts that run other programs, pretty much like a windows batch file.
how can I run a command from python such that the program when run, will replace the script? The program is interactive (for instance, unison) and keeps printing lines and asking for user input all the time.
So, just running a program and printing the output won't suffice. The program has to takeover the script's input/output, pretty mcuh like running the command from a .bat file.
I tried os.execl but it keeps telling me "invalid arguments", also, it doesn't find the program name (doesn't search the PATH variable); I have to give it the full path ..?!
basically, in a batch script I can write:
unison profile
how can I achieve the same effect in python?
EDIT:
I found out it can be done with os.system( ... ) and since I cannot accept my own answer, I'm closing the question.
EDIT: this was supposed to be a comment, but when I posted it I didn't have much points.
Thanks Claudiu, that's pretty much what I want, except for a little thing: I want the function to end when the program exits, but when I try it on unison, it doesn't return control to the python script, but to the windows command line environment
>>> os.execlp("unison")
C:\>Usage: unison [options]
or unison root1 root2 [options]
or unison profilename [options]
For a list of options, type "unison -help".
For a tutorial on basic usage, type "unison -doc tutorial".
For other documentation, type "unison -doc topics".
C:\>
C:\>
C:\>
how to get around this?
You should create a new processess using the subprocess module.
I'm not fluent in windows processes but its Popen function is cross-platform, and should be preffered to OS specific solutions.
EDIT: I maintain that you should prefer the Subprocess module to os.* OS specific functions, it is cross-platform and more pythonic (just google it). You can wait for the result easily, and cleanly:
import os
import subprocess
unison = os.path.join(os.path.curdir, "unison")
p = subprocess.Popen(unison)
p.wait()
I found out that os.system does what I want,
Thanks for all that tried to help.
os.system("dir")
runs the command just as if it was run from a batch file
import subprocess
proc = subprocess.Popen(['unison', 'profile'], stderr=subprocess.PIPE,
stdout=subprocess.PIPE, stdin=subprocess.PIPE)
proc.stdin.write('user input')
print proc.stdout.read()
This should help you get started. Please edit your question with more information if you want a more detailed answer!
os.execlp should work. This will search your path for the command. Don't give it any args if they're not necessary:
>>> import os
>>> os.execlp("cmd")
D:\Documents and Settings\Claudiu>Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.
D:\Documents and Settings\Claudiu>