python on linux can't find file inside function - python

I'm writing a script on python 2.7.12 on linux with a bunch of functions that run external programs...
at some point, I have a function that runs a program, which generates an external file. The next step of the function is to read the external file and do some processing.
The function is
def RunProgram(input, options)
input_file=str(input)
options=str(options)
cmd=str('program + ' input_file + '--flag ' + options + ' --out temp.log &> /dev/null')
#print(cmd)
#print(cmd)
os.system(cmd)
with open('path_to_file/temp.log') as fp:
for i, line in enumerate(fp):
if i == 2:
#print(line)
solution=str(line) #stores 3rd line of log file
elif i > 2:
break
return solution
Somehow, although the external program runs and I see temp.log created from a bash shell, the function exits with the error
IOError: [Errno 2] No such file or directory: 'path_to_file/temp.log'
if in the function after os.system(cmd) I place
print(os.path.exists('path_to_file/temp.log'))
print(os.path.isfile('path_to_file/temp.log'))
I get 2 false, but if I run those commands after running the function and getting the error i get True for both and I see the file in the directory using ls.
Once I run the function again with temp.log already existing, the function works.
I have checked with os.getcwd() and the session is running in the correct dirrectory. I also checked I have read permissions on temp.log
..any ideas?

This is probably a race condition: When your code wants to read the output from the file, the program isn't finished yet and the output file doesn't exist yet. Try a loop with "sleep" waiting for the file you want to read to become available. Another possibility is that that the file permissions don't match.

Related

Getting permission error when calling a program from another drive with subprocess

I have a script that has 4 lines of code:
import subprocess
folderAdd = r"D:\Program Files (x86)\someapp\"
result = subprocess.run(['"' + folderAdd +'someProgram.exe"','"' + folderAdd +'somefile.ext"'], stdout=subprocess.PIPE)
print(result.stdout)
I've edited the code slightly to remove the specifics of the files/folders (since I assume that's not the issue?). The someProgram.exe is a go lang program I've made, the somefile.ext is a file that I pass to the go land program using the command line (eg the syntax in command line is: "someProgram.ext somefile.ext". The issue I'm having is when I run this script (which is stored on my E drive - so that's the working directory) I get the following error:
PermissionError: [WinError 5] Access is denied
I've tried running this python script from within spyder (my ide of choice) and from command line. Both of which I've tried running as administrator (based on this question/answer). I still get the same permission error. Is there any other way around this?
you're adding double quotes that should not be here.
Also you should join path using python's facility : os.path.join
(https://docs.python.org/3.8/library/os.path.html#os.path.join)
If you only what stdout, you can use subprocess.check_outout
(https://docs.python.org/3.8/library/subprocess.html#subprocess.check_output)
import subprocess
folderAdd = r"D:\Program Files (x86)\someapp"
print(subprocess.check_output([os.path.join(folderAdd, 'someProgram.exe'), os.path.join(folderAdd, 'somefile.ext'])

making a file executable via subprocess in python

I'm trying to make a bash file executable via a python program. Right now it looks like this:
p = subprocess.Popen(chmod u+x, bashName)
bashName being the name of the bash file I'm making executable, and I'm receiving the error:
FileNotFoundError: [Errno 2] No such file or directory: 'chmod u+x
/home/#####/Desktop/music/addSong/bashFileName'
I've tried this and it didn't fare any better
subprocess.call('chmod u+x /home/stoplight25/Desktop/music/addSong/'+bashName)
I've tried reading the documentation on subprocess but it's a bit beyond my comprehension. Could someone explain how to make a file executable with subprocess.
Expected:
make a new bash file with the correct contents and name, make it executable
Result:
a bash file with the right contents and name but isn't executable.
You have to pass the arguments as a list, not as a string or python tries to pass the whole string with spaces & args & all to the system as the executable (or use shell=True which I don't recommend). Also check return code just in case:
subprocess.check_call(['chmod','u+x','/home/stoplight25/Desktop/music/addSong/'+bashName])
Or you could use pure python to access the file permissions (get file current permissions, add user execute mask, apply os.chmod):
import os
my_file = os.path.join('/home/stoplight25/Desktop/music/addSong',bashName)
new_mode = os.stat(my_file).st_mode | 0o100
os.chmod(my_file,new_mode)
This should work:
import subprocess
command = 'chmod u+x /home/stoplight25/Desktop/music/addSong/' + bashName
process = subprocess.Popen(command.split(), stdout=subprocess.PIPE)
output, error = process.communicate()

Docker + Django executing external node.js script

I have a problem with executing my node js script. When i run this script normally from command line everything is ok.
But when i want to execute that script directly from django it will print error like this:
the first line says that you are in the code before that line of code what execute that script. Second is path and is correct as you see. Third and to the error are files in that directory (I was checking if executing commands from command line works)
I recall that this django project runs in docker container so i think that error might be there.
Here is my line of code where i run that script in my view.py:
def prepare_log_img(picture):
string_without_header = re.sub('^data:image/.+;base64,', '', picture)
img_data = base64.b64decode(string_without_header)
filename = SITE_ROOT + "/faceId/logged.png"
with open(filename, 'wb') as f:
f.write(img_data)
os.chdir(SITE_ROOT + "/static/scripts")
print("Pred face detection")
print(SITE_ROOT + "/static/scripts")
print(os.system("ls"))
os.system("node face-detection.js logged.png")
The last line is that executing. Anyone knows what is the problem? Thank you.
The operating system executing that node face-detection.js logged.png line doesn't know where to go to find your node installation. You can probably fix that by giving the full path to your node installation.
In a regular terminal window type which node, to find out where it is installed, for me the result was /usr/sbin/node. So if I were to run that command it should probably be:
os.system("/usr/sbin/node face-detection.js logged.png")

Trying to run a python script with crontab every hour, but one section of the python code does not execute

I wrote a script using python and selenium that tries to register for a class called puppy play. Crontab runs the script every hour and sends any output to a file called "cronpup.log". This section of code is in my python script and it just checks to see if the registration was successful or not then appends the results to the file "pup.log".
# Pup Logger
f = open("pup.log", "a+")
f.write(time.strftime("%Y-%m-%d %H:%M:%S "))
if pups == 1:
f.write("Pups!\n")
elif pups == 0:
f.write("No Pups\n")
else:
f.write("Ruh Roh, Something is wrong\n")
f.close()
This creates the "pup.log" file with entries like the following
$ pup.log
2014-10-17 17:49:18 No Pups
2014-10-17 19:37:28 No Pups
I can run the python script just fine from the terminal, but when crontab executes the script no new entries are made in "pup.log". I've checked the output from crontab and have found nothing. Here is crontab's output
$ cronpup.log
.
----------------------------------------------------------------------
Ran 1 test in 81.314s
OK
It seems like crontab is just ignoring that section of the code, but that seems pretty silly. Any ideas how to get this working?
The line
f = open("pup.log", "a+")
is your problem. Open is looking the the current working directory for pup.log, creating it if necessary, and appending to it. If you run from the terminal while in the same directory as the python script, that's where pup.log will appear. The cwd when running from cron is the home directory of the user the job is running as, so when run from cron it's dropping a pup.log file somewhere else on your system.
You can either hardcode a full path, or use
os.chdir(os.path.dirname(os.path.abspath(__file__)))
to set the current working directory to the directory the python file is in, or modify the above to put pup.log whereever you like.

Can't open file with complete path name on Linux in Python

I recently installed Ubuntu to run alongside my Windows OS. I wanted to see how a certain script ran in Ubuntu and it ran fine for the most part. There is this one part of my code that causes trouble. I try to open a file using the os.system('gnome-open ' + filePath) command but I can't get it to open a file unless I only specify the file name not the directory (i.e. I have to say "data.txt", I can't say "home/user/workspace/project/src/data.txt" because it'll say the file/directory doesn't exist). Also I made multiple copies of this file for testing purposes and some of them have parentheses in their names, when I attempt to open these files I get the error "sh: Syntax error: "(" unexpected" and it doesn't specify a line of code so I assume it's the line that's accessed when I call this function. Below is the code I'm referencing.
def openFileOfItem(self, row):
print fileList[row]
if platform.system() == "Windows":
os.startfile(fileList[row])
else:
if platform.system() == "Linux":
os.system('gnome-open ' + nameList[row])
else:
os.system('open %s' % fileList[row])
And some sample output:
/home/damian/workspace/Kde Gen/src/data.txt
Error showing url: Error stating file '/home/damian/workspace/Kde': No such file or directory
/home/damian/workspace/Kde Gen/src/data (copy).txt
sh: Syntax error: "(" unexpected
You are dumping the string directly to the command line without escaping - this results in errors when the shell tries to execute the command you provided to it. You need to escape your file path first. Since you are using Python 2.7, try using pipes.quote
from pipes import quote
def openFileOfItem(self, row):
print fileList[row]
if platform.system() == "Windows":
os.startfile(fileList[row])
else:
if platform.system() == "Linux":
os.system('gnome-open %s' % quote(nameList[row]))
else:
os.system('open %s' % quote(fileList[row]))
You are effectively running a shell command, and it's getting tripped up by the spaces in your path. Instead of quoting the arguments, it's cleaner to do this:
import subprocess
subprocess.call([ "gnome-open", nameList[row] ] )
AFAICT, the error message is because you have space in the path. quote the path should fix the problem.
os.system('gnome-open "%s"' % nameList[row])
I can't say "home/user/workspace/project/src/data.txt" because it'll say the file/directory doesn't exist)
Did you mean "/home/user/workspace/project/src/data.txt" ? Otherwise, it's relative to the current directory.
Other than that, on UNIX it's customary to use the version that runs the program directly and passes an argument vector, otherwise the shell (used by system()) might do weird stuff which you told it without intending to (that is called injection).
os.spawnvp(os.P_WAIT, "gnome-open", ["gnome-open", nameList[row]])

Categories

Resources