Path: csiph.com!x330-a1.tempe.blueboxinc.net!usenet.pasdenom.info!aioe.org!feeder.news-service.com!newsfeed.xs4all.nl!newsfeed6.news.xs4all.nl!xs4all!newsgate.cistron.nl!newsgate.news.xs4all.nl!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.000 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'else:': 0.03; 'python.': 0.04; 'elif': 0.04; 'thread,': 0.04; '-if': 0.05; 'encoded': 0.05; 'chunk': 0.07; 'complaining': 0.07; 'raises': 0.07; 'python': 0.08; "(it's": 0.09; 'attribute': 0.09; 'bash': 0.09; 'encoder': 0.09; 'exception:': 0.09; 'received:80.91': 0.09; 'received:80.91.229': 0.09; 'received:80.91.229.12': 0.09; 'received:gmane.org': 0.09; 'received:list': 0.09; 'received:lo.gmane.org': 0.09; 'subprocess': 0.09; 'writable': 0.09; 'output': 0.11; 'exception': 0.12; 'win32': 0.12; 'skip:f 30': 0.13; 'wrote:': 0.15; '(moving': 0.16; '193': 0.16; '__init__': 0.16; 'bash,': 0.16; 'c2pwrite': 0.16; 'encoders': 0.16; 'errread,': 0.16; 'errwrite': 0.16; 'failure.': 0.16; 'msvcrt': 0.16; 'received:dip.t-dialin.net': 0.16; 'received:t-dialin.net': 0.16; 'stderr': 0.16; 'subject:Trying': 0.16; 'holds': 0.16; '>>>': 0.16; 'repeated': 0.19; 'string,': 0.19; 'yet.': 0.19; 'command': 0.19; "haven't": 0.21; 'input': 0.21; '(most': 0.21; 'skip:m 30': 0.21; 'loop': 0.22; 'trying': 0.23; 'code': 0.24; 'traceback': 0.25; 'windows': 0.27; "i'm": 0.27; 'right,': 0.28; 'skip:" 30': 0.28; 'script': 0.29; 'object': 0.30; 'module': 0.30; '-of': 0.30; 'blocks': 0.30; 'decorators': 0.30; 'from:addr:web.de': 0.30; 'nested': 0.30; 'andrew': 0.32; 'earlier': 0.32; 'used,': 0.32; 'error': 0.33; 'break': 0.33; 'ideal': 0.33; 'header:X-Complaints-To:1': 0.34; 'there': 0.34; 'points': 0.34; 'to:addr:python-list': 0.34; 'clearly': 0.35; 'assignment': 0.35; 'function.': 0.35; 'identical': 0.35; 'last):': 0.35; 'skip:" 50': 0.35; 'try:': 0.35; 'pretty': 0.35; "isn't": 0.35; 'options': 0.36; 'file': 0.36; 'skip:" 10': 0.36; 'idea': 0.36; 'option': 0.37; 'but': 0.37; 'some': 0.37; 'using': 0.38; 'received:org': 0.38; 'subject:: ': 0.38; 'else': 0.38; 'put': 0.38; 'common': 0.39; 'header:Mime-Version:1': 0.39; 'to:addr:python.org': 0.39; "there's": 0.39; 'skip:s 20': 0.40; 'where': 0.40; 'give': 0.60; 'note:': 0.68; 'safe': 0.70; 'learned': 0.73; 'wav': 0.84 X-Injected-Via-Gmane: http://gmane.org/ To: python-list@python.org From: Peter Otten <__peter__@web.de> Subject: Re: Trying to chain processes together on a pipeline Date: Tue, 28 Jun 2011 08:32:35 +0200 Organization: None References: <4E096D3B.3080300@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset="ISO-8859-1" Content-Transfer-Encoding: 7Bit X-Gmane-NNTP-Posting-Host: p50849ff0.dip.t-dialin.net X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 132 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1309242751 news6.xs4all.nl 4366 [2001:888:2000:d::a6]:54490 X-Complaints-To: abuse@xs4all.nl Xref: x330-a1.tempe.blueboxinc.net comp.lang.python:8523 Andrew Berg wrote: > I'm working on an audio/video converter script (moving from bash to > Python for some extra functionality), and part of it is chaining the > audio decoder (FFmpeg) either into SoX to change the volume and then to > the Nero AAC encoder or directly into the Nero encoder. This is the > chunk of code from my working bash script to give an idea of what I'm > trying to accomplish (it's indented because it's nested inside a while > loop and an if statement): >> if [ "$process_audio" = "true" ] >> then >> if [ $vol == 1.0 ] >> then >> ffmpeg -i "${ifile_a}" -f wav - 2>$nul | neroaacenc >> -ignorelength -q 0.4 -if - -of ${prefix}${zero}${ep}.m4a >> else >> # the pipeline-as-file option of sox fails on Windows >> 7, so I use the safe method since there's only one pipeline going into >> sox >> ffmpeg -i "${ifile_a}" -f sox - 2>$nul | sox -t sox - >> -t wav - vol $vol 2>$nul | neroaacenc -ignorelength -q 0.4 -if - -of >> ${prefix}${zero}${ep}.m4a >> fi >> else >> echo "Audio skipped." >> fi > This is pretty easy and straightforward in bash, but not so in Python. > This is what I have in Python (queue[position] points to an object I > create earlier that holds a bunch of info on what needs to be encoded - > input and output file names, command line options for the various > encoders used, and so forth), but clearly it has some problems: >> try: >> ffmpeg_proc = subprocess.Popen(queue[position].ffmpeg_cmd, >> stdout=subprocess.PIPE, stderr=os.devnull) >> except WindowsError: >> error_info = str(sys.exc_info()[1]) >> last_win_error_num = find_win_error_no(error_msg=error_info) >> if last_win_error_num == '2': # Error 2 = 'The system cannot >> find the file specified' >> logger.critical('Could not execute ' + >> queue[position].ffmpeg_exe + ': File not found.') >> elif last_win_error_num == '193': # Error 193 = '%1 is not a >> valid Win32 application' >> logger.critical('Could not execute ' + >> queue[position].ffmpeg_exe + ': It\'s not a valid Win32 application.') >> break >> if queue[position].vol != 1: >> try: >> sox_proc = subprocess.Popen(queue[position].sox_cmd, >> stdin=ffmpeg_proc.stdout, stdout=subprocess.PIPE, stderr=os.devnull) >> except WindowsError: >> error_info = str(sys.exc_info()[1]) >> last_win_error_num = find_win_error_no(error_msg=error_info) >> if last_win_error_num == '2': # Error 2 = 'The system >> cannot find the file specified' >> logger.critical('Could not execute ' + >> queue[position].sox_exe + ': File not found.') >> elif last_win_error_num == '193': # Error 193 = '%1 is not >> a valid Win32 application' >> logger.critical('Could not execute ' + >> queue[position].sox_exe + ': It\'s not a valid Win32 application.') >> break >> wav_pipe = sox_proc.stdout >> else: >> wav_pipe = ffmpeg_proc.stdout >> try: >> nero_aac_proc = subprocess.Popen(queue[position].nero_aac_cmd, >> stdin=wav_pipe) >> except WindowsError: >> error_info = str(sys.exc_info()[1]) >> last_win_error_num = find_win_error_no(error_msg=error_info) >> if last_win_error_num == '2': # Error 2 = 'The system cannot >> find the file specified' >> logger.critical('Could not execute ' + >> queue[position].sox_exe + ': File not found.') >> elif last_win_error_num == '193': # Error 193 = '%1 is not a >> valid Win32 application' >> logger.critical('Could not execute ' + >> queue[position].sox_exe + ': It\'s not a valid Win32 application.') >> break >> >> ffmpeg_proc.wait() >> if queue[position].vol != 1: >> sox_proc.wait() >> nero_aac_proc.wait() >> break > Note: those break statements are there to break out of the while loop > this is in. > Firstly, that first assignment to ffmpeg_proc raises an exception: >> Traceback (most recent call last): >> File "C:\Users\Bahamut\workspace\Disillusion\disillusion.py", line >> 288, in >> ffmpeg_proc = subprocess.Popen(queue[position].ffmpeg_cmd, >> stdout=subprocess.PIPE, stderr=os.devnull) >> File "C:\Python32\lib\subprocess.py", line 700, in __init__ >> errread, errwrite) = self._get_handles(stdin, stdout, stderr) >> File "C:\Python32\lib\subprocess.py", line 861, in _get_handles >> errwrite = msvcrt.get_osfhandle(stderr.fileno()) >> AttributeError: 'str' object has no attribute 'fileno' > I'm not really sure what it's complaining about since the exception > propagates from the msvcrt module through the subprocess module into my > program. I'm thinking it has to do my stderr assignment, but if that's > not right, I don't know what is. os.devnull is a string, but you need a writable file: >>> subprocess.call(["ls"], stdout=os.devnull) Traceback (most recent call last): File "", line 1, in File "/usr/lib/python2.6/subprocess.py", line 470, in call return Popen(*popenargs, **kwargs).wait() File "/usr/lib/python2.6/subprocess.py", line 614, in __init__ errread, errwrite) = self._get_handles(stdin, stdout, stderr) File "/usr/lib/python2.6/subprocess.py", line 971, in _get_handles c2pwrite = stdout.fileno() AttributeError: 'str' object has no attribute 'fileno' >>> subprocess.call(["ls"], stdout=open(os.devnull, "w")) 0 > Secondly, there are no Popen.stdout.close() calls because I'm not sure > where to put them. > Thirdly, I have nearly identical except WindowsError: blocks repeated - > I'm sure I can avoid this with decorators as suggested in a recent > thread, but I haven't learned decorators yet. This code isn't very > complete; I'm trying to get it to work in ideal conditions first, then > worry about how to handle failure. Start with factoring out common code into a good old function. > Using Python 3 on Windows 7.