Path: csiph.com!usenet.pasdenom.info!weretis.net!feeder1.news.weretis.net!feeder.erje.net!1.eu.feeder.erje.net!newsfeed.xs4all.nl!newsfeed2a.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.001 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'skip:[ 20': 0.03; 'subject:Python': 0.05; '"""': 0.05; 'context': 0.05; 'paths': 0.05; 'append': 0.07; 'objects,': 0.07; 'collapsed': 0.09; 'input,': 0.09; 'os.path': 0.09; 'overwrite': 0.09; 'typed': 0.09; 'cc:addr:python-list': 0.10; 'python': 0.11; 'python.': 0.11; 'def': 0.14; 'file,': 0.15; 'output': 0.15; 'bash,': 0.16; 'bigger.': 0.16; 'executor': 0.16; 'subprocess': 0.16; 'url:html)': 0.16; '{0}': 0.16; 'skip:{ 20': 0.18; 'input': 0.18; 'thanks,': 0.19; '(see': 0.20; 'cc:2**0': 0.21; 'cc:addr:python.org': 0.21; 'complete,': 0.22; 'symbolic': 0.22; 'text,': 0.22; 'try:': 0.22; 'cc:no real name:2**0': 0.23; 'code,': 0.23; 'code.': 0.23; 'normally': 0.23; 'slightly': 0.23; 'import': 0.24; 'header:In-Reply-To:1': 0.24; 'idea': 0.26; 'skip:_ 20': 0.26; 'possibility': 0.27; 'said,': 0.27; 'skip:e 30': 0.27; 'start,': 0.27; 'convert': 0.29; "skip:' 10": 0.30; 'print': 0.31; 'code': 0.31; "can't": 0.32; 'implement': 0.32; 'point': 0.33; 'url:python': 0.33; 'problem': 0.33; 'skip:_ 30': 0.33; 'adjust': 0.33; 'case,': 0.34; 'running': 0.34; 'file': 0.34; 'received:google.com': 0.34; 'message-id:@gmail.com': 0.35; 'could': 0.35; 'question,': 0.35; 'really': 0.35; 'but': 0.36; 'too': 0.36; 'url:org': 0.36; 'there': 0.36; 'skip:{ 10': 0.36; 'url:library': 0.36; 'should': 0.37; 'display': 0.37; 'subject:: ': 0.37; 'thought': 0.37; "skip:' 20": 0.37; 'instead': 0.38; 'difference': 0.38; 'someone': 0.38; 'files': 0.38; 'test': 0.39; 'url:2': 0.39; 'does': 0.39; 'url:docs': 0.39; 'received:192': 0.39; 'build': 0.40; 'some': 0.40; 'url:3': 0.60; 'your': 0.60; "you'll": 0.61; 'real': 0.61; 'header:Message-Id:1': 0.62; 'more': 0.62; 'different': 0.64; 'it!': 0.64; 'charset:windows-1252': 0.65; 'jobs': 0.67; 'printing,': 0.72; 'race': 0.72; 'carefully': 0.76; 'paper': 0.78; 'returns.': 0.84; 'subject:Using': 0.84; 'try,': 0.84; 'to:none': 0.90; 'try.': 0.91; 'good,': 0.93 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=content-type:mime-version:subject:from:in-reply-to:date:cc :content-transfer-encoding:message-id:references; bh=Z7CL8MtWnARWcKUk/Nt53wTKaJDs2EXwkO9/LZrFelc=; b=VzJebQ43W6SNobwDNABaqKzs1M9O5dcgcfbwgkR0ws0iFyHBScjmnQO7lKtAbe7osO xHyYgEpOYjIHqPLQn1Ujrj4nKopvZ9NsH7Wd/fd/R8jVq5LkT1/u4v1FgXsdW77H+gfb kPbscyxG+7h1+lVecg+Id8YMgxv3LLWKxjG6fm5mVQuWcqbPcOthOSz9urf/Vjh3mtPI I4rm2Z9MuYVnmIhS6abxVR712kC66bg7Ehd8P3oNHf/U7L11Nyet74HPszrcbL+9p6JH 4sguV1QqzBtJMqLjMT1QCOsUWhqHnryBngR2iNL4Vdh0So7Z+LH40dgrLFHsr58tUZZA Isig== X-Received: by 10.140.83.168 with SMTP id j37mr18870969qgd.18.1433081671304; Sun, 31 May 2015 07:14:31 -0700 (PDT) Content-Type: text/plain; charset=windows-1252 Mime-Version: 1.0 (Mac OS X Mail 6.6 \(1510\)) Subject: Re: Using Python instead of Bash From: Cem Karan In-Reply-To: <87h9qsnckl.fsf@Equus.decebal.nl> Date: Sun, 31 May 2015 10:14:29 -0400 Cc: python-list@python.org Content-Transfer-Encoding: quoted-printable References: <87h9qsnckl.fsf@Equus.decebal.nl> X-Mailer: Apple Mail (2.1510) X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.20+ 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: 109 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1433081674 news.xs4all.nl 2965 [2001:888:2000:d::a6]:47802 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:91574 > I help someone that has problems reading. For this I take photo's of > text, use convert from ImageMagick to make a good contrast (original > paper is grey) and use lpr to print it a little bigger. >=20 > Normally I would implement this in Bash, but I thought it a good idea > to implement it in Python. This is my first try: > import glob > import subprocess >=20 > treshold =3D 66 > count =3D 0 > for input in sorted(glob.glob('*.JPG')): > count +=3D 1 > output =3D '{0:02d}.png'.format(count) > print('Going to convert {0} to {1}'.format(input, output)) > p =3D subprocess.Popen(['convert', '-threshold', = '{0}%'.format(treshold), input, output]) > p.wait() > print('Going to print {0}'.format(output)) > p =3D subprocess.Popen(['lpr', '-o', 'fit-to-page', '-o', = 'media=3DA4', output]) > p.wait() >=20 > There have to be some improvements: display before printing, > possibility to change threshold, =85 But is this a good start, or = should > I do it differently? As a first try, I think its pretty good, but to really answer your = question, I think we could use a little more information. =20 - Are you using python 2, or python 3? There are slightly easier ways = to do this using concurrent.futures objects, but they are only available = under python 3. (See = https://docs.python.org/3/library/concurrent.futures.html) - In either case, subprocess.call(), subprocess.check_call(), or = subprocess.check_output() may be easier to use. That said, your code is = perfectly fine! The only real difference is that subprocess.call() will = automatically wait for the call to complete, so you don't need to use = p.wait() from above. (See = https://docs.python.org/2.7/library/subprocess.html, and = https://docs.python.org/3/library/subprocess.html)=20 The following codes does the conversion in parallel, and submits the = jobs to the printer serially. That should ensure that the printed = output is also in sorted order, but you might want to double check = before relying on it too much. The major problem with it is that you = can't display the output before printing; since everything is running in = parallel, you'll have race conditions if you try. **I DID NOT TEST THIS = CODE, I JUST TYPED IT OUT IN MY MAIL CLIENT!** Please test it carefully = before relying on it! """ import subprocess import concurrent.futures import glob import os.path _THRESHOLD =3D 66 def _collect_filenames(): files =3D glob.glob('*.JPG') # I build a set of the real paths so that if you have=20 # symbolic links that all point to the same file, they # they are automatically collapsed to a single file real_files =3D {os.path.realpath(x) for x in files} base_files =3D [os.path.splitext(x)[0] for x in real_files] return base_files def _convert(base_file_name): """ This code is slightly different from your code. Instead of using numbers as names, I use the base name of file and append '.png' to it. You may need to adjust this to ensure you don't overwrite anything. """ input =3D base_file_name + ".JPG" output =3D base_file_name + ".png" subprocess.call(['convert', '-threshold', '{0}%'.format(_THRESHOLD), = input, output]) def _print_files_in_order(base_files): base_files.sort() for f in base_files: output =3D f + ".png" subprocess.call(['lpr', '-o', 'fit-to-page', '-o', 'media=3DA4', = output]) def driver(): base_files =3D _collect_filenames() # If you use an executor as a context manager, then the # executor will wait until all of the submitted jobs finish # before it returns. The submitted jobs will execute in # parallel. with concurrent.futures.ProcessPoolExecutor() as executor: for f in base_files: executor.submit(_convert_and_print, f) _print_files_in_order(base_files) """ Thanks, Cem Karan=