Replacing commands.getoutput with subprocess - python

I am struggling to replace commands.getoutput with subprocess.
Please see the codes below:
import subprocess
import commands
dir = subprocess.check_output(['pwd'])
print dir+"/*.py"
dir = commands.getoutput('pwd')
print dir+"/*.py"
Here's the ouput:
/home/akik/py
/*.py
/home/akik/py/*.py
Please help me fixing it.

getoutput() strips the newline printed by pwd command. You have to do it manually with check_output():
from subprocess import check_output
dirname = check_output(['pwd']).rstrip("\n")
print dirname + "/*.py"

Related

'FileNotFoundError' When Running R From Python

I am trying to run some R from python but I keep running into:
'FileNotFoundError: [WinError 2] The system cannot find the file specified'
I have tried searching for this problem but none of the solutions have worked.
The files are in the same directory and I'm running windows.
Here is my attempt the python:
import subprocess
import sys
from os import path
myfile = path.abspath(path.join(path.dirname(__file__), "test.R")
cmd = ['Rscript', myfile]
result = subprocess.check_output(cmd, universal_newlines=True)
print(result)
sys.stdout.flush()
The R code is just a simple Hello World.
Hope that you have added Rscript to path variable. Use below code to change your working directory as current directory
import subprocess
import sys
from os import path
sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__)), "."))
os.chdir(os.path.abspath(os.path.dirname(__file__)))
myfile = path.abspath(path.join(path.dirname(__file__), "test.R")
cmd = ['Rscript', myfile]
result = subprocess.check_output(cmd, universal_newlines=True)
print(result)
sys.stdout.flush()

Python script won't print when called from another python script

I have two scripts. The first script outputs to a file a list of folders and files, then it calls a second python script to read that file and print it to screen. The second script is called but nothing ever prints to the screen and I'm not sure why. No error message is thrown.
First Script:
#!/bin/python
from subprocess import call
import os.path
import os
def main():
userRequest=raw_input("""Type the path and folder name that you'd like to list all files for.
The format should begin with a slash '/' and not have an ending slash '/'
Example (/var/log) *Remember capital vs. lower case does matter* :""")
userInputCheck(userRequest)
def userInputCheck(userRequest):
lastCharacter=userRequest[-1:]
if lastCharacter=="/":
userRequest=userRequest[:-1]
folderCheck=os.path.isdir(userRequest)
if folderCheck != True:
print("\nSorry, '"+userRequest+"' does not exist, please try again.\n")
requestUserInput()
else:
extractFileList(userRequest)
def extractFileList(userRequest):
fileList=open('/tmp/fileList.txt', 'a')
for folderName, subFolderName, listFiles in os.walk(userRequest):
fileList.write(folderName+":\n")
for fileName in listFiles:
fileList.write(fileName+"\n")
fileList.write("\n")
fileList.close
os.system("readFile.py /tmp/fileList.txt")
if os.path.isfile("/tmp/fileList.txt"):
os.remove("/tmp/fileList.txt")
if __name__ == "__main__":
main()
Second Script:
#!/bin/python
import sys
userFile=sys.argv[1]
f = open(userFile, 'r')
fileInfo=f.read()
sys.stdout.write(fileInfo)
sys.stdout.flush()
f.close

white space in filename python 3.4.2

I have created this small prog to search all PDF's in a directory, determine if they are searchable or not and then move them to the appropriate directory.
I am new to Python and it is probably not the best way but it does work until the file name has White Space in it and I get the following returned.
Any help would be appreciated.
>>> os.system("pdffonts.exe " + pdfFile + "> output.txt")
99
import os
import glob
import shutil
directory = os.chdir("C:\MyDir") # Change working directory
fileDir = glob.glob('*.pdf') # Create a list of all PDF's in declared directory
numFiles = len(fileDir) # Lenght of list
startFile = 0 # Counter variable
seekWord = "TrueType"
while startFile < numFiles:
pdfFile=fileDir[startFile]
os.system("pdffonts.exe " + pdfFile + "> output.txt")
file1output = open("output.txt","r")
fileContent = file1output.read()
if seekWord in fileContent:
shutil.move(pdfFile , "NO_OCR")
else: shutil.move(pdfFile, "OCR")
startFile = startFile + 1
os.system() uses the shell to execute your command. You'd have to quote your filename for the shell to recognise spaces as part of the file, you could do so with the shlex.quote() function:
os.system("pdffonts.exe " + shlex.quote(pdfFile) + "> output.txt")
However, there is no reason at all to use os.system() and the shell. You should use the subprocess.run() function and configure that to pass back the output without using redirection or a shell:
import subprocess
seekWord = b"TrueType"
for pdfFile in fileDir:
result = subprocess.run(["pdffonts.exe", pdfFile], stdout=subprocess.PIPE)
fileContent = result.stdout
if seekWord in fileContent:
# ...
Because pdfFile is passed to pdffonts.exe directly there is no need to worry about a shell parsing and whitespace no longer matters.
Note that I changed seekWord to be a bytes literal instead as result.stdout is a bytes value (no need to try to decode the result to Unicode here).
It seems the problem doesn't come from python, but the Windows shell. You need to enclose in quotation mark. As I don't have your program pdffonts.exe, I cannot debug. I also made your code more pythonic
import os
import glob
import shutil
directory = os.chdir("C:\MyDir") # Change working directory
fileDir = glob.glob('*.pdf') # Create a list of all PDF's in declared directory
seekWord = "TrueType"
for pdfFile in fileDir:
os.system('pdffonts.exe "{0}"> output.txt'.format(pdfFile))
file1output = open("output.txt","r")
fileContent = file1output.read()
if seekWord in fileContent:
shutil.move(pdfFile , "NO_OCR")
else:
shutil.move(pdfFile, "OCR")

Python: Trying to put the contents of a folder into a text file:

I'm in the process of writing a python script that takes two arguments that will allow me to output the contents of a folder to a text file for me to use for another process. The snippet of I have is below:
#!/usr/bin/python
import cv2
import numpy as np
import random
import sys
import os
import fileinput
#Variables:
img_path= str(sys.argv[1])
file_path = str(sys.argv[2])
print img_path
print file_path
cmd = 'find ' + img_path + '/*.png | sed -e "s/^/\"/g;s/$/\"/g" >' + file_path + '/desc.txt'
print "command: ", cmd
#Generate desc.txt file:
os.system(cmd)
When I try and run that from my command line, I get the following output, and I have no idea how to fix it.
sh: 1: s/$//g: not found
I tested the command I am using by running the following command in a fresh terminal instance, and it works out fine:
images/*.png | sed -e "s/^/\"/g;s/$/\"/g" > desc.txt
Can anyone see why my snippet isn't working? When I run it, I get an empty file...
Thanks in advance!
its not sending the full text for your regular expression through to bash because of how python processes and escapes string content, so the best quickest solution would be to just manually escape the back slashes in the string, because python thinks they currently are escape codes. so change this line:
cmd = 'find ' + img_path + '/*.png | sed -e "s/^/\"/g;s/$/\"/g" >' + file_path + '/desc.txt'
to this:
cmd = 'find ' + img_path + '/*.png | sed -e "s/^/\\"/g;s/$/\\"/g" >' + file_path + '/desc.txt'
and that should work for you.
although, the comment on your question has a great point, you could totally just do it from python, something like:
import os
import sys
def main():
# variables
img_path= str(sys.argv[1])
file_path = str(sys.argv[2])
with open(file_path,'w') as f:
f.writelines(['{}\n'.format(line) for line in os.listdir(img_path) if line.endswith('*.png')])
if __name__ == "__main__":
main()
I fully agree with Kyle. My recommendation is to do using only python code better than call bash commands from your code. Here it is my recommended code, it is longer and not as optimal than the aforementioned one, but IMHO it is a more easy to understand solution.
#!/usr/bin/python
import glob
import sys
import os
# Taking arguments
img_path = str(sys.argv[1])
file_path = str(sys.argv[2])
# lets put the target filename in a variable (it is better than hardcoding it)
file_name = 'desc.txt'
# folder_separator is used to define how your operating system separates folders (unix / and windows \)
folder_separator = '\\' # Windows folders
# folder_separator = '/' # Unix folders
# better if you make sure that the target folder exists
if not os.path.exists(file_path):
# if it does not exist, you create it
os.makedirs(file_path)
# Create the target file (write mode).
outfile = open(file_path + '/' + file_name, 'w')
# loop over folder contents
for fname in glob.iglob("%s/*" % img_path):
# for every file found you take only the name (assuming that structure is folder/file.ext)
file_name_in_imgPath = fname.split('\\')[1]
# we want to avoid to write 'folders' in the target file
if os.path.isfile(file_name_in_imgPath):
# write filename in the target file
outfile.write(str(file_name_in_imgPath) + '\n')
outfile.close()

Using Python to execute a command on every file in a folder

I'm trying to create a Python script that would :
Look into the folder "/input"
For each video in that folder, run a mencoder command (to transcode them to something playable on my phone)
Once mencoder has finished his run, delete the original video.
That doesn't seem too hard, but I suck at python :)
Any ideas on what the script should look like ?
Bonus question : Should I use
os.system
or
subprocess.call
?
Subprocess.call seems to allow for a more readable script, since I can write the command like this :
cmdLine = ['mencoder',
sourceVideo,
'-ovc',
'copy',
'-oac',
'copy',
'-ss',
'00:02:54',
'-endpos',
'00:00:54',
'-o',
destinationVideo]
EDIT : Ok, that works :
import os, subprocess
bitrate = '100'
mencoder = 'C:\\Program Files\\_utilitaires\\MPlayer-1.0rc2\\mencoder.exe'
inputdir = 'C:\\Documents and Settings\\Administrator\\Desktop\\input'
outputdir = 'C:\\Documents and Settings\\Administrator\\Desktop\\output'
for fichier in os.listdir(inputdir):
print 'fichier :' + fichier
sourceVideo = inputdir + '\\' + fichier
destinationVideo = outputdir + '\\' + fichier[:-4] + ".mp4"
commande = [mencoder,
'-of',
'lavf',
[...]
'-mc',
'0',
sourceVideo,
'-o',
destinationVideo]
subprocess.call(commande)
os.remove(sourceVideo)
raw_input('Press Enter to exit')
I've removed the mencoder command, for clarity and because I'm still working on it.
Thanks to everyone for your input.
To find all the filenames use os.listdir().
Then you loop over the filenames. Like so:
import os
for filename in os.listdir('dirname'):
callthecommandhere(blablahbla, filename, foo)
If you prefer subprocess, use subprocess. :-)
Use os.walk to iterate recursively over directory content:
import os
root_dir = '.'
for directory, subdirectories, files in os.walk(root_dir):
for file in files:
print os.path.join(directory, file)
No real difference between os.system and subprocess.call here - unless you have to deal with strangely named files (filenames including spaces, quotation marks and so on). If this is the case, subprocess.call is definitely better, because you don't need to do any shell-quoting on file names. os.system is better when you need to accept any valid shell command, e.g. received from user in the configuration file.
The new recommend way in Python3 is to use pathlib:
from pathlib import Path
mydir = Path("path/to/my/dir")
for file in mydir.glob('*.mp4'):
print(file.name)
# do your stuff
Instead of *.mp4 you can use any filter, even a recursive one like **/*.mp4. If you want to use more than one extension, you can simply iterate all with * or **/* (recursive) and check every file's extension with file.name.endswith(('.mp4', '.webp', '.avi', '.wmv', '.mov'))
Python might be overkill for this.
for file in *; do mencoder -some options "$file"; rm -f "$file" ; done
The rm -f "$file" deletes the files.
AVI to MPG (pick your extensions):
files = os.listdir('/input')
for sourceVideo in files:
if sourceVideo[-4:] != ".avi"
continue
destinationVideo = sourceVideo[:-4] + ".mpg"
cmdLine = ['mencoder', sourceVideo, '-ovc', 'copy', '-oac', 'copy', '-ss',
'00:02:54', '-endpos', '00:00:54', '-o', destinationVideo]
output1 = Popen(cmdLine, stdout=PIPE).communicate()[0]
print output1
output2 = Popen(['del', sourceVideo], stdout=PIPE).communicate()[0]
print output2
Or you could use the os.path.walk function, which does more work for you than just os.walk:
A stupid example:
def walk_func(blah_args, dirname,names):
print ' '.join(('In ',dirname,', called with ',blah_args))
for name in names:
print 'Walked on ' + name
if __name__ == '__main__':
import os.path
directory = './'
arguments = '[args go here]'
os.path.walk(directory,walk_func,arguments)
I had a similar problem, with a lot of help from the web and this post I made a small application, my target is VCD and SVCD and I don't delete the source but I reckon it will be fairly easy to adapt to your own needs.
It can convert 1 video and cut it or can convert all videos in a folder, rename them and put them in a subfolder /VCD
I also add a small interface, hope someone else find it useful!
I put the code and file in here btw: http://tequilaphp.wordpress.com/2010/08/27/learning-python-making-a-svcd-gui/

Categories