i've been trying to run sox in a python script but it can't the output file and gives me [errno2]
def AudioToSpectrogram(self, files, pixel_per_sec, height, width):
file_name = ("tmp_{}.png").format(random.randint(0, 100000))
command = "sox -V0 {} -n remix 1 rate 10k spectrogram -y {} -x {} -X {} -m -r -o {}".format(files, height, width, pixel_per_sex, file_name)
p = Popen(command, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
Output, errors = p.communicate()
If errors:
Print(errors)
Image = Image.open(file_name)
Os.remove(file_name)
Return np.array(image)
This is the error it gives
Exception: [errno2] No such file or Directory: 'tmp_47483.png'
I hope you could give me some pointers since i am still new in this field, thanks in advance!
Assuming tmp_47483.png is in fact being created, the problem is likely that the command is placing the file in a different folder and Python can't find it inside the current working directory. The
# manually set the full path (make sure the backslashes are escaped by putting two each)
file_name = f"C:\\Full\\Path\\To\\File\\tmp_{random.randint(0, 100000}.png"
# use the os module to join the path
base_dir = "C:\\Full\\Path\\To\\File"
file_name = os.path.join(base_dir, f"tmp_{random.randint(0, 100000}.png")
# if you want it to appear in the same folder as your script:
CWD = os.path.dirname(os.path.realpath(__file__)) # mostly fool-proof way of getting a script's Current Working Directory
file_name = os.path.join(CWD, f"tmp_{random.randint(0, 100000}.png")
Try these and see if they help. If not, make sure that command is actually working and outputting a file somewhere.
Related
I am rather new to Python and have been trying to run a .cmd file with it, but it won't run it from the correct location. My file Run_setup.cmd, is setting up another a different software with a bunch of related files and so I have sequestered them to their own folder for my sanity.
Currently I can get the .cmd file to run from the same location as my source code. I know I am messing up the file path for it with cwd=r'%s' based on what the documentation says, but I don't get how.
If cwd is not None, the function changes the working directory to cwd before executing the child. cwd can be a str and path-like object. In particular, the function looks for executable (or for the first item in args) relative to cwd if the executable path is a relative path.
I currently have it using cwd=r' C:\LargeFolder\Files\CorrectFolder' based off this post, and it seems that it works for any file path, but I can't seem to get it to work for me.
from subprocess import Popen
def runCmdfile():
# File Path to source code: 'C:\LargeFolder\Files'
myDir = os.getcwd()
# File Path to .cmd file: 'C:\LargeFolder\Files\CorrectFolder'
myDir = myDir + '\CorrectFolder'
runThis = Popen('Run_setup.cmd', cwd=r'%s' % myDir)
stdout, stderr = runThis.communicate()
What am I missing here, and furthermore what is the purpose of using cwd=r' ' ?
this one works for me:
def runCmdfile():
# File Path to source code: 'C:\LargeFolder\Files'
myDir = os.getcwd()
# File Path to .cmd file: 'C:\LargeFolder\Files\CorrectFolder'
myDir = os.path.join(myDir, 'CorrectFolder')
# Popen does not take cwd into account for the file to execute
# so we build the FULL PATH on our own
runThis = Popen(os.path.join(myDir, 'Run_setup.cmd'), cwd=myDir)
stdout, stderr = runThis.communicate()
the parameter is cwd=. The r"" part only needs to exist in the definition of your string, to have a raw string and make python ignore special sequences using backslashes.
Since your string comes from os.getcwd, you don't need it.
def runCmdfile():
# File Path to source code: 'C:\LargeFolder\Files'
myDir = os.getcwd()
# File Path to .cmd file: 'C:\LargeFolder\Files\CorrectFolder'
myDir = os.path.join(myDir, 'CorrectFolder')
runThis = Popen('Run_setup.cmd', cwd=myDir)
stdout, stderr = runThis.communicate()
Your error is due to not escaping your \.
You need to escape your "\" where you're adding in your subfolder and then you should be good to go.
myDir = myDir + '\CorrectFolder'
should be
myDir = myDir + '\\CorrectFolder'
For a project I need to automate the conversion of plenty .svg-files to .dxf-files for further processing.
Situation: One directory with plenty .svg-files which should be converted to .dxf (no matter if the .dxf files are in the same diretory or in a subfolder, dxf name should be svg name)
I can do that with Inkscape GUI which also works for importing the .dxf files in CAD programs, but as mentioned I need to automate that. (I've only written in Python so far).
My thought: I open the files in Inkscape via command line. Exporting in png-format would be possible via command with following code:
from subprocess import call
import os
svg_dir = "C:\\temp\\layers\\"
files = [svg_dir + i for i in os.listdir(svg_dir) if ".svg" in i]
dir = r"C:\Program Files\Inkscape"
for i in files:
cmdline = "Inkscape -z -f "+ i +" -e "+ i + ".png"
rc = call("start cmd /K " + cmdline, cwd=dir, shell=True)
But I do not really unterstand Inkscape extensions. I only know that I need dxf_outlines.py/.inx in the extension directory. I always need the same export options so could I just rewrite the Python code for that and run it via command in Inkscape?
Or would there be any solution without any extra software like Inkscape in Python? As far as I've seen there isn't.
I came up with a slightly different solution but still made my way to the needed .dxf-files. I saved my figures in Python as .eps-files and could convert them with just one command line with pstoedit.
def eps_to_dxf():
eps_list = [i for i in os.listdir(eps_directory) if ".eps" in i]
work_directory = "C:\Program Files\pstoedit"
for i in eps_list:
input_file = i.split(".")[0]
output_file = input_file + ".dxf"
cmdline = "pstoedit -f dxf_s " + eps_directory + i + " " + eps_directory + output_file
subprocess.check_call(cmdline, cwd=work_directory, shell=True)
This is a Linux command to convert svg file to dxf with Inkscape
python /usr/share/inkscape/extensions/dxf12_outlines.py --output="output.dxf" "input.svg"
I would like to run the following command in a python script, I also want to make it loop over several videos in a folder. This is the command I want to run.
ffmpeg -i mymovie.avi -f image2 -vf fps=fps=1 output%d.png
I want to fit it in something like this:
import ffmpy
import os
path = './Videos/MyVideos/'
for filename in os.listdir(path):
name = filename.replace('.avi','')
os.mkdir(os.path.join(path,name))
*ffmpeg command here*
I found a wrapper for ffmpeg called ffmpy, could this be a solution?
From a brief look at FFMPY, you could do this using ffmpy.FFmpeg, as that allows any and all FFMPEG command line options, including -f. -- Click the link for documentation.
You could do the FFMPEG command with os.system. You'll need to import OS anyway to iterate through the files.
You would need to iterate through all the files in a directory though. This would be the more challenging bit, it's quite easy with a for loop though.
for filename in os.listdir(path):
if (filename.endswith(".mp4")): #or .avi, .mpeg, whatever.
os.system("ffmpeg -i {0} -f image2 -vf fps=fps=1 output%d.png".format(filename))
else:
continue
The above code iterates through the directory at path, and uses command prompt to execute your given FFMPEG command, using the filename (if it's a video file) in place of mymovie.avi
Dont have reputation to comment, hence adding another response.
Another version of ocelot's answer with the more readable f-string syntax of python -
for filename in os.listdir(path):
if (filename.endswith(".mp4")): #or .avi, .mpeg, whatever.
os.system(f'ffmpeg -i {filename} -f image2 -vf fps=fps=1 output%d.png')
else:
continue
Try pydemux in https://github.com/Tee0125/pydemux. Pydemux module can extract video frames as in Pillow Image format
from PyDemux import Video
v = Video.open('video.mov')
i = 0
while True:
im = v.get_frame()
if im is None:
break
im.save('output%d.png'%i)
i = i + 1
This is a way to use ffmpeg in a python script, e.g. for extracting the last 10 seconds of every video:
ffmpeg -sseof -10 -i input.mp4 output.mp4
To apply this to a whole folder of mp4 files:
from pathlib import Path
import os
suffix = ".mp4"
input_path= Path.home() / "Desktop/foo"
file_paths= [subp for subp in input_path.rglob('*') if suffix == subp.suffix]
file_paths.sort()
output_path = Path.home() / "Desktop/foo/new"
output_path.mkdir(parents=True, exist_ok=True)
for file_p in file_paths:
input = str(file_p)
output = str( output_path / file_p.name )
command = f"ffmpeg -sseof -10 -i {input} {output}"
print(command)
os.system(command)
Please bear with me, I've not used python before, and I'm trying to get some rendering done as quick as possible and getting stopped in my tracks with this.
I'm outputting the .ifd files to a network drive (Z:), and they are stored in a folder structure like;
Z:
- \0001
- \0002
- \0003
I need to iterate over the ifd files within a single folder, but the number of files is not static so there also needs to be a definable range (1-300, 1-2500, etc). The script therefore has to be able to take an additional two arguments for a start and end range.
On each iteration it executes something called 'mantra' using this statement;
mantra -f file.FRAMENUMBER.ifd outputFile.FRAMENUMBER.png
I've found a script on the internet that is supposed to do something similar;
import sys, os
#import command line args
args = sys.argv
# get args as string
szEndRange = args.pop()
szStartRange = args.pop()
#convert args to int
nStartRange = int(szStartRange, 10);
nEndRange = int(szEndRange, 10);
nOrd = len(szStartRange);
#generate ID range
arVals = range(nStartRange, nEndRange+1);
for nID in arVals:
szFormat = 'mantra -V a -f testDebris.%%(id)0%(nOrd)dd.ifd' % {"nOrd": nOrd};
line = szFormat % {"id": nID};
os.system(line);
The problem I'm having is that I can't get it to work. It seems to iterate, and do something - but it looks like it's just spitting out ifds into a different folder somewhere.
TLDR;
I need a script which will at least take two arguments;
startFrame
endFrame
and from those create a frameRange, which is then used to iterate over all ifd files executing the following command;
mantra -f fileName.currentframe.ifd fileName.currentFrame.png
If I were able to specify the filename and the files directory and output directory that'd be great too. I've tried manually doing that but there must be some convention to that I don't know as it was coming up with errors when I tried (stopping at the colon).
If anyone could hook me up or point me in the right direction that'd be swell. I know I should try and learn python, but I'm at my wits end with the rendering and need a helping hand.
import os, subprocess, sys
if len(sys.argv) != 3:
print('Must have 2 arguments!')
print('Correct usage is "python answer.py input_dir output_dir" ')
exit()
input_dir = sys.argv[1]
output_dir = sys.argv[2]
input_file_extension = '.txt'
cmd = 'currentframe'
# iterate over the contents of the directory
for f in os.listdir(input_dir):
# index of last period in string
fi = f.rfind('.')
# separate filename from extension
file_name = f[:fi]
file_ext = f[fi:]
# create args
input_str = '%s.%s.ifd' % (os.path.join(input_dir, file_name), cmd)
output_str = '%s.%s.png' % (os.path.join(output_dir + file_name), cmd)
cli_args = ['mantra', '-f', input_str, output_str]
#call function
if subprocess.call(cli_args, shell=True):
print('An error has occurred with command "%s"' % ' '.join(cli_args))
This should be sufficient for you to either use currently or with slight modification.
Instead of specifically inputting a start and end range you could just do:
import os
path, dirs, files = os.walk("/Your/Path/Here").next()
nEndRange = len(files)
#generate ID range
arVals = range(1, nEndRange+1);
The command os.walk() counts the # of files in the folder that you specified.
Although, an even easier way of getting your desired output is like this:
import os
for filename in os.listdir('dirname'):
szFormat = 'mantra -f ' + filename + ' outputFile.FRAMENUMBER.png'
line = szFormat % {"id": filename}; # you might need to play around with this formatting
os.system(line);
Because os.listdir() iterates through the specified directory and filename is every file in that directory, so you don't even need to count them.
a little help building the command.
for nID in arVals:
command = 'mantra -V a -f '
infile = '{0}.{1:04d}.ifd '.format(filename, id)
outfile = '{0}.{1:04d}.png '.format(filename, id)
os.system(command + infile + outfile);
and definitely use os.walk or os.listdir like #logic recommends
for file in os.listdir("Z:"):
filebase = os.path.splitext(file)[0]
command = 'mantra -V a -f {0}.ifd {0}.png'.format(filebase)
I have the following command
lessc lessc xyz.less > xyz.css
I want to run that command in python for which i have written this code
try:
project_path = settings.PROJECT_ROOT
less_path = os.path.join(project_path, "static\\less")
css_path = os.path.join(project_path, "static\\css")
except Exception as e:
print traceback.format_exc()
less_file = [f for f in os.listdir(less_path) if isfile(join(less_path, f))]
for files in less_file:
file_name = os.path.splitext(files)[0]
cmd = '%s\%s > %s\%s' % (less_path, files, css_path, file_name + '.css')
p = subprocess.Popen(['lessc', cmd], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
but it gives error windowerror 2 cannot find the path specifies
Make sure that 'lessc' is in your path, you could try using the full path to lessc instead.
You don't need to use shell style redirection with Popen like this, check the subprocess.Popen docs
Here is an example of how to do it without shell redirection:
import subprocess
lessc_command = '/path/to/lessc'
less_file_path = '/path/to/input.less'
css_file_path = '/path/to/output.css'
with open(css_file_path, 'w') as css_file:
less_process = subprocess.Popen([lessc_command, less_file_path], stdout=css_file)
less_process.communicate()