I know there are some topic on Stack Overflow about this. But none of these make any sense to me. I am new to both python and perl and trying my best to understand. I would like to run a perl script from a piece of python code.
executing the perl script in command prompt goes as following:
perl perlscript.pl input.bopt7 output.xml
I would like to run this command from my python code.
I have tried the following:
pipe = subprocess.Popen(["perlscript.pl" , "input.bopt7" , "output.xml"], stdout=subprocess.PIPE)
but this does not work. I get an error saying it is not a valid win32 ...
I need no input or output from this script. Just need to run it once.
You need to include the perl command itself when executing a perl script:
pipe = subprocess.Popen(["perl", "perlscript.pl" , "input.bopt7" , "output.xml"], stdout=subprocess.PIPE)
You did the same thing on the command line prompt; the Popen class cannot guess from the perlscript.pl file that you wanted to run this script with Perl. :-)
Did you try to add perl to Popen arguments (just as you do on the command line)?
pipe = subprocess.Popen(["perl", "perlscript.pl" , "input.bopt7" , "output.xml"], stdout=subprocess.PIPE)
In your example, Windows tries to execute "perlscript.pl" as a Win32 executable, since this is the first parameter you specified, and fails because it doesn't contain the proper binary header (since it is a text file).
The first argument should be perl.exe, if perl.exe is in your PATH; or the full path to the executable as all the rest are arguments to perl.exe.
Also make sure you put the full path for perlscript.pl and input.bopt7.
Related
I am currently working with a software package that allows you to create Python scripts and execute them from inside that package. The results of any script are saved back into the program. When the script executes, it does not show a command prompt window.
Is there an easy way to open a command prompt window from inside the script and pass over information for display, such as a dataframe header, a string or a list of values?
I have found from earlier SO posts that I can use:
import os
os.system('cmd /k "Some random text"')
This works as expected, but when I use the following code:
x = str(2 * 2)
output= f'cmd /k "{x}"'
os.system(output)
The number 4 is passed to the command window, but the following message appears:
'4' is not recognized as an internal or external command, operable program or batch file.
The answer is in the question.
'4' is not recognized as an internal or external command, operable program or batch file.
Open cmd and type anything it will give error unless we type something which is recognized by cmd. e.g a help command.
if there is something we want to type in cmd and let it get processed/printed on console we use a command
echo
in your program only the echo command was missing, which will let your output get printed on cmd.
Last but not the least, always remember the ZEN of Python
Use subprocess instead
The `subprocess` has some more benefits compared to `Os`:
The subprocess module provides a consistent interface to creating and working with additional processes.
It offers a higher-level interface than some of the other available modules, and is intended to replace functions such as os.system(), os.spawn*(), os.popen*(), popen2.*() and commands.*().
Reference
If you want to write something like to print 4 in another cmd tab, do like this:
import subprocess
var = '4'
subprocess.Popen(['start','cmd','/k','echo',var], shell = True, stdin = subprocess.PIPE, stdout = subprocess.PIPE, text = True)
Result:
It opens another cmd tab and passes a command such as echo var.
My perl script is at path:
a/perl/perlScript.pl
my python script is at path:
a/python/pythonScript.py
pythonScript.py gets an argument from stdin, and returns result to stdout. From perlScript.pl , I want to run pythonScript.py with the argument hi to stdin, and save the results in some variable. That's what I tried:
my $ret = `../python/pythonScript.py < hi`;
but I got the following error:
The system cannot find the path specified.
Can you explain the path can't be found?
The qx operator (backticks) starts a shell (sh), in which prog < input syntax expects a file named input from which it will read lines and feed them to the program prog. But you want the python script to receive on its STDIN the string hi instead, not lines of a file named hi.
One way is to directly do that, my $ret = qx(echo "hi" | python_script).
But I'd suggest to consider using modules for this. Here is a simple example with IPC::Run3
use warnings;
use strict;
use feature 'say';
use IPC::Run3;
my #cmd = ('program', 'arg1', 'arg2');
my $in = "hi";
run3 \#cmd, \$in, \my $out;
say "script's stdout: $out";
The program is the path to your script if it is executable, or perhaps python script.py. This will be run by system so the output is obtained once that completes, what is consistent with the attempt in the question. See documentation for module's operation.
This module is intended to be simple while "satisfy 99% of the need for using system, qx, and open3 [...]. For far more power and control see IPC::Run.
You're getting this error because you're using shell redirection instead of just passing an argument
../python/pythonScript.py < hi
tells your shell to read input from a file called hi in the current directory, rather than using it as an argument. What you mean to do is
my $ret = `../python/pythonScript.py hi`;
Which correctly executes your python script with the hi argument, and returns the result to the variable $ret.
The Some of the other answers assume that hi must be passed as a command line parameter to the Python script but the asker says it comes from stdin.
Thus:
my $ret = `echo "hi" | ../python/pythonScript.py`;
To launch your external script you can do
system "python ../python/pythonScript.py hi";
and then in your python script
import sys
def yourFct(a, b):
...
if __name__== "__main__":
yourFct(sys.argv[1])
you can have more informations on the python part here
I have a a file structure like the following (Windows):
D:\
dir_1\
batch_1.bat
dir_1a\
batch_2.bat
dir_2\
main.py
For the sake of this question, batch_1.bat simply calls batch_2.bat, and looks like:
cd dir_1a
start batch_2.bat %*
Opening batch_1.bat from a command prompt indeed opens batch_2.bat as it's supposed to, and from there on, everything is golden.
Now I want my Python file, D:\dir_2\main.py, to spawn a new process which starts batch_1.bat, which in turn should start batch_2.bat. So I figured the following Python code should work:
import subprocess
subprocess.Popen(['cd "D:/dir_1"', "start batch_1.bat"], shell=True)
This results in "The system cannot find the path specified" being printed to my Python console. (No error is raised, of course.) This is due to the first command. I get the same result even if I cut it down to:
subprocess.Popen(['cd "D:/"'], shell=True)
I also tried starting the batch file directly, like so:
subprocess.Popen("start D:/dir_1/batch_1.bat", shell=True)
For reasons that I don't entirely get, this seems to just open a windows command prompt, in dir_2.
If I forego the start part of this command, then my Python process is going to end up waiting for batch_1 to finish, which I don't want. But it does get a little further:
subprocess.Popen("D:/dir_1/batch_1.bat", shell=True)
This results in batch_1.bat successfully executing... in dir_2, the directory of the Python script, rather than the directory of batch_1.bat, which results in it not being able to find dir_1a\ and hence, batch_2.bat is not executed at all.
I am left highly confused. What am I doing wrong, and what should I be doing instead?
Your question is answered here: Python specify popen working directory via argument
In a nutshell, just pass an optional cwd argument to Popen:
subprocess.Popen(["batch_1.bat"], shell=True, cwd=r'd:\<your path>\dir1')
I am writing a script to open notepad.exe using subprocess.Popen()
import subprocess
command = '%windir%\system32\\notepad.exe'
process = subprocess.Popen(command)
output = process.communicate()
print(output[0])
This throws a FileNotFoundError
Is it possible to change/add to the above code to make it work with relative paths?
I did try to run the script from C:\Windows> after moving it there, which again failed. Also set the shell=True, but failed as well.
Writing a similar script using os.popen() works ok with relative paths, regardless which directory the script is run from, but as far as I understand popen is not the way forward..
Early steps in the world of programming/Python. Any input much appreciated.
Use os.path.expandvars to expand %windir%:
command = os.path.expandvars('%windir%\\system32\\notepad.exe')
The result is a path that then can be passed to subprocess.Popen.
subprocess.Popen does not expand environment variables such as %windir%. The shell might but you really should not depend on shell=True to do that.
Pro tip: whenever you get an error asking the system to execute a command, print the command (and, if applicable, the current working directory). The results will often surprise you.
In your case, I suspect you're just missing a backslash. Use this instead:
command = '%windir%\\system32\\notepad.exe'
Before you make that change, try printing the value of command immediately after assignment. I think you'll find the leading "s" in "system" is missing, and that the mistake is obvious.
HTH.
You could use raw strings to avoid having to double-up your backslashes.
command = r'%windir%\system32\notepad.exe'
How do you specify what directory the python module subprocess uses to execute commands? I want to run a C program and process it's output in Python in near realtime.
I want to excute the command (this runs my makefile for my C program:
make run_pci
In:
/home/ecorbett/hello_world_pthread
I also want to process the output from the C program in Python. I'm new to Python so example code would be greatly appreciated!
Thanks,
Edward
Use the cwd argument to Popen, call, check_call or check_output. E.g.
subprocess.check_output(["make", "run_pci"],
cwd="/home/ecorbett/hello_world_pthread")
Edit: ok, now I understand what you mean by "near realtime". Try
p = subprocess.Popen(["make", "run_pci"],
stdout=subprocess.PIPE,
cwd="/home/ecorbett/hello_world_pthread")
for ln in p.stdout:
# do processing
Read the documentation. You can specify it with the cwd argument, otherwise it uses the current directory of the parent (i.e., the script running the subprocess).