Why subprocess.call () is showing error in linux? - python

Let us consider Linux platform where I need to execute a program called smart.exe which uses input.dat file. Both the files are placed in the same directory with each file having the same file permission 777.
Now if I run the following command in the terminal window smart.exe is fully executed without any error.
$./smart.exe input.dat
On the other hand, if I use the following python script called my_script.py placed in the same directory, then I get an error.
my_script.py has the following code:
#!/usr/bin/python
import os, subprocess
exit_code = subprocess.call("./smart.exe input.dat", shell = False)
The error is as follows:
File "my_script.py", line 4, in <module>
exit_code = subprocess.call("./smart.exe input.dat", shell = False)
File "/usr/lib64/python2.6/subprocess.py", line 478, in call
p = Popen(*popenargs, **kwargs)
File "/usr/lib64/python2.6/subprocess.py", line 642, in __init__
errread, errwrite)
File "/usr/lib64/python2.6/subprocess.py", line 1234, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
Can someone please tell me why this is happening. Please note that the smart.exe should take around 10 sec to fully complete. This may be a clue for the problem.
Please also advise if there is any other way to run smart.exe from my_script.py. Your solution is much appreciated!

You should decide if you want shell support or not.
If you want the shell to be used (which is not necessary here), you should use exit_code = subprocess.call("./smart.exe input.dat", shell=True). Then the shell interprets your command line.
If you don't want it (as you don't need it and want to avoid unnecessary complexity), you should do exit_code = subprocess.call(["./smart.exe", "input.dat"], shell=False).
(And there is no point naming your binarys .exe under Linux.)

Related

Python: Can't find file even though file referenced exists

I'm getting this error when trying to run a Python script. Is it saying that it can't find subprocess.py? Because I found it in the location it's listing there, so I doubt that's the issue. What file can't it find?
Traceback (most recent call last):
File "D:\Projects\PythonMathPlots\MandelbrotVideoGenerator.py", line 201, in <module>
run( ['open', 'MandelbrotZoom.mp4'] )
File "C:\Users\Aaron\AppData\Local\Programs\Python\Python37\lib\subprocess.py", line 472, in run
with Popen(*popenargs, **kwargs) as process:
File "C:\Users\Aaron\AppData\Local\Programs\Python\Python37\lib\subprocess.py", line 775, in __init__
restore_signals, start_new_session)
File "C:\Users\Aaron\AppData\Local\Programs\Python\Python37\lib\subprocess.py", line 1178, in _execute_child
startupinfo)
FileNotFoundError: [WinError 2] The system cannot find the file specified
You may need to put the full path in the run(...) command, to the open file, and the path to the .mp4 file as well.
Most likely, open does not exist on your system and you have to use the name of the video player software instead.
Make sure the user you're running the script as has read permission for the file.
You may also try with subprocess.Popen(args, shell=True). The use of shell=True may be useful.
Also, use a path defined as path = os.path.join(filepath, filename) and then before passing the path to Popen, assert if os.path.exists(path)==True.
But note that there are some downsides to using shell=True:
Actual meaning of 'shell=True' in subprocess
https://medium.com/python-pandemonium/a-trap-of-shell-true-in-the-subprocess-module-6db7fc66cdfd

How to make a Python script "tab-complete" directories in terminal?

I have a Shell Script, let's say run.sh, which reads a user input from keyboard and then does some specific tasks. For some technical reasons I'm migrating this script to Python, e.g run.py, in order to achieve the exact same goal.
In the run.sh file I ask the user a input, which is typically a file in the file system, so I gave the option of "tab-completing" it and I achieved it simply through the line:
read -e -p "Choose a file: " file
The -e flag does the job of tab-completing users input. For example, if user's current directory is project, which follows the structure:
project
-- src
-- shared
-- lib
-- imgs
-- image.png
-- include
-- README.txt
and the input file is image.png they could proceed as follow:
sh<tab>i<tab><tab>
the result would be shared/imgs/image.png.
Now how do I achieve it inside a Python script? You may believe there are tons of related questions but I haven't been able to reproduce this exact same result in run.py.
What I have tried so far:
1. Python's os module:
import os
os.system("read -e -p 'Choose a file:'")
Output: sh: 1: read: Illegal option -e
2. Python's subprocess module
import subprocess
subprocess.run(['read', '-e', '-p', 'Choose a file'])
Output:
Traceback (most recent call last):
File "run.py", line 26, in <module>
subprocess.run(['read', '-e', '-p', 'Choose a file'])
File "/usr/lib/python3.7/subprocess.py", line 453, in run
with Popen(*popenargs, **kwargs) as process:
File "/usr/lib/python3.7/subprocess.py", line 756, in __init__
restore_signals, start_new_session)
File "/usr/lib/python3.7/subprocess.py", line 1499, in _execute_child
raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'read': 'read'
3. Python's readline module
import readline
readline.parse_and_bind("tab:complete")
file = input("Choose a file: ")
This one almost seems to work, but there is one big issue: it completes only the files in user's current directory. If user hit s<tab> then src and shared show up, but if they hit sh<tab> the liband imgs directory do not show up.
I'd like some elegant and simple way to achieve this, but I am convinced this might be a little more difficult than expected. Are there any other approaches that can solve this problem?
Set sensible completion delimiters:
import readline
readline.set_completer_delims(' \t\n=')
readline.parse_and_bind("tab: complete")
option = input("Tab complete a file: ")
By default, readline will delimit based on any of the following:
>>> import readline
>>> readline.get_completer_delims()
' \t\n`~!##$%^&*()-=+[{]}\\|;:\'",<>/?'
Since / is part of this set, anything after a / will be completed independently of anything before it. This obviously makes no sense when you're trying to complete a file path.

Running Python code: subprocess.check_output(), getting error: [Winerror 2]

I'm running some Python code that is meant to run an Apache Maven program on a file and produce an output:
import os, subprocess
os.chdir("C:/Users/Mohammad/Google Drive/PhD/Spyder workspace/production-consumption/logtool-examples/")
logtoolDir = "C:/Users/Mohammad/Google Drive/PhD/Spyder workspace/production-consumption/logtool-examples/"
processEnv = {'JAVA_HOME': 'C:/Program Files/Java/jdk1.8.0_66/jre',
'mvn': 'C:/Program Files/apache-maven-3.3.3/bin/'}
#processEnv = "C:/Program Files/Java/jdk1.8.0_66"
args = 'org.powertac.logtool.example.ProductionConsumption D:/PowerTAC/Logs/2015/log/powertac-sim-1.state testrunoutput.data'
subprocess.check_output(['mvn', ' exec:exec',
' -Dexec.args=' + args],
env = processEnv,
cwd = logtoolDir)
However, it gives me this error:
File "C:/Users/Mohammad/Google Drive/PhD/Spyder workspace/production-consumption/test.py", line 25, in <module>
cwd = logtoolDir)
File "C:\WinPython-64bit-3.4.3.6\python-3.4.3.amd64\lib\subprocess.py", line 607, in check_output
with Popen(*popenargs, stdout=PIPE, **kwargs) as process:
File "C:\WinPython-64bit-3.4.3.6\python-3.4.3.amd64\lib\subprocess.py", line 859, in __init__
restore_signals, start_new_session)
File "C:\WinPython-64bit-3.4.3.6\python-3.4.3.amd64\lib\subprocess.py", line 1112, in _execute_child
startupinfo)
FileNotFoundError: [WinError 2] The system cannot find the file specified
I've investigated some things and I've narrowed it down to what I'm expecting is _winapi.CreateProcess being unable to find the Apache Maven installation (and run the mvn command). The installation is already in my path env variables (the line runs just fine through CMD). It may also be true that I've somehow defined the directories wrongly, but I fail to find a problem there... Can anyone offer a suggestion on how to fix this issue?
Cheers.
You can try appending "shell = True" to the arguments passed to subprocess like so:
subprocess.check_output(['mvn', ' exec:exec',
' -Dexec.args=' + args],
env = processEnv,
cwd = logtoolDir, shell = True)
Though as it says here, this can be a security risk if the contents of the call can be determined by an external source, but I can't tell whether that's the case from the code you've given.

Crontab error : Windows can not find the specified file

I am trying to use this example script to test crontab in python:
from crontab import CronTab
tab = CronTab(user='www',fake_tab='True')
cmd = '/var/www/pjr-env/bin/python /var/www/PRJ/job.py'
cron_job = tab.new(cmd)
cron_job.minute().every(5)
#writes content to crontab
tab.write()
print tab.render()
It returns with an error 'fake_tab' not defined. If i remove this parameter and call the function
like this: CronTab(user='www'). I returns the following error :
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
tab = CronTab(user='www')
File "C:\Python27\lib\site-packages\crontab.py", line 160, in __init__
self.read(tabfile)
File "C:\Python27\lib\site-packages\crontab.py", line 183, in read
p = sp.Popen(self._read_execute(), stdout=sp.PIPE)
File "C:\Python27\lib\subprocess.py", line 711, in __init__
errread, errwrite)
File "C:\Python27\lib\subprocess.py", line 948, in _execute_child
startupinfo)
WindowsError: [Error 2] The system cannot find the file specified
Does any one know, what am I missing?
I think that Crontab is a Unix/Linux concept. Not sure if it can work under windows. This Page says "Windows support works for manual crontabs only". Not sure what he means by that though.
As the author of python-crontab I can report that the documentation has been updated. It's clear ineffective given the number of people puzzled over what manual means.
If you do this:
mem_cron = CronTab(tab="""
* * * * * command # comment
""")
You should have a memory only crontab. Same if you do a file as a crontab:
file_cron = CronTab(tabfile='filename.tab')
I'm always looking to improve the code and documentation, so please do email me.
The easiest way I found to make crontab find my job was:
In settings.py (I'm using django) I defined these variables:
CRONTAB_EXECUTABLE='C:/Users/myuser/myvirtualenv/Lib/site-packages/django_crontab/crontab.py'
CRONTAB_DJANGO_PROJECT_NAME='myproject'
CRONTAB_DJANGO_MANAGE_PATH='C:/Users/myuser/myvirtualenv/myproject/manage.py'
CRONTAB_PYTHON_EXECUTABLE='C:/Users/myuser/AppData/Local/Programs/Python/Python36-32/pythonw.exe'
Pay attention to the slash. It must be leaned to the right or it causes a syntax error.
By this way crontab will find the job or whatever you are trying to execute. In my case I was trying:
C:\Users\bsi\mlearning3\src>python manage.py crontab add

cp: cannot stat ... No such file or directory

In a python script, I issue the command:
def copy_file(csv_file): #csv_file = "wpa-01.csv"
subprocess.call(["cp",csv_file,"tempfile.csv"])
I get the error:
cp: cannot stat 'wpa-01.csv' : No such file or directory
-tempfile.csv is a valid file, it is open
-I have tried adding quotes around wpa-01.csv, ie
subprocess.call(["cp","\"wpa-01.csv\"","tempfile.csv"])
-I have tried adding escape character in front of the '-'
-I have tried including the directory in front og the file name
-I am using gedit on a local Linux machine (so its not a dos2unix kind of solution), but the script is being ran on a remote Raspberry Pi
in every case I get the same error. I am at a loss for solutions. any suggestions?
***Here is the problem: "wpa-01.csv" is a 'live'/'dynamic' file. There is an active process that is updating that file in real time. I think that the file will have to be 'dead'/'static' in order to issue cp command? This is not ideal for my purposes. Is there a way to work around this like changing the mod or something? If not I suppose I can try to find an alternative solution.
print "wpa-01.csv" in os.listdir(".") #make sure file really does exist
subprocess.call(["cp","\"wpa-01.csv\"","tempfile.csv"],shell=True)
My guess is you need to set shell=True so that it uses your path to find cp executes in your shell ... if you don't use shell=True it wont use your path ...
Unfortunately all it is is a guess ...
Anyway, here is some supporting evidence:
>>> subprocess.call("copy tmp5.py tmp55.py")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python26\lib\subprocess.py", line 470, in call
return Popen(*popenargs, **kwargs).wait()
File "C:\Python26\lib\subprocess.py", line 623, in __init__
errread, errwrite)
File "C:\Python26\lib\subprocess.py", line 833, in _execute_child
startupinfo)
WindowsError: [Error 2] The system cannot find the file specified
>>> subprocess.call("copy tmp5.py tmp55.py",shell=True)
1 file(s) copied.
0

Categories