subprocesses, stdin/out, ttys, and beating insubordinate processes into the ground

Steve Holden steve at holdenweb.com
Wed Jun 7 08:30:24 EDT 2006


Jonathan Smith wrote:
> First a bit about what I'm trying to do. I need a function which takes a 
> patchfile and patches a source directory. Thats it. However, I need to 
> be able to do so no matter what the patchlevel (-px) of the diff is. So, 
> my solution is to just try to patch until it works or you try a level 
> more than 3. However, if you have a reversed patch, or patch can't find 
> the right file, GNU patch tries to ask for input and I don't want that. 
> I know that patch will run non-interactively when backgrounded in a 
> shell (no controlling tty). This is what I've tried so far:
> 
>      def patchme(self, provides, f, destDir, patchlevels):
>          for patchlevel in patchlevels:
>              patchArgs = ['patch', '-d', destDir, '-p%s'%patchlevel, ]
>              if self.backup:
>                  patchArgs.append(['-b', '-z', self.backup])
>              if self.extraArgs:
>                  patchArgs.append(self.extraArgs)
> 
>              log.info('attempting to patch the source with file %s and 
> patchlevel %s' % (f,patchlevel))
>              p1 = subprocess.Popen([provides, f], 
> stdout=subprocess.PIPE, shell=False)
>              p2 = subprocess.Popen(patchArgs, stdin=p1.stdout, shell=False)
>              message = p2.communicate()[0] # patch seems to use stdout 
> for everything, even errors
> 
>              if message != None and self.patcherror.search(message):
>                  os.kill(p2.pid, signal.SIGTERM)
>              elif p2.wait():
>                  log.info('patch did not apply with path level %s' % 
> patchlevel)
>                  print message
>              else:
>                  return
>          log.error('could not apply the patch to your build dir')
> 
> 
> However, I still get an interactive prompt, no matter what I try! Using 
> shell=False did not help, nor did trying to kill the pid if python sees 
> a line from patch which isn't saying what its patching or giving info on 
> a specific hunk. Any suggestions?
> 
> -smithj
> 
> PS: if you're a maintainer for GNU patch, a --non-interactive would be 
> really nice ;-) (and no, -f and -t aren't good enough as they force 
> other things that I don't want)

If the technique you want to use doesn't work, it's usually a good idea 
to try another technique. Your current approach is pretty dreadful, when 
it would be relatively easy to parse the start of the patchfile and 
determine the appropriate level (i.e. -p argument) by finding the file 
to be patched.

Neither your approach nor my suggested alternative is that good when the 
patch is modifying a file whose name appears at several points in the 
directory hierarchy (as may be the case with README, for example), so it 
might be even better to parse the whole patchfile and ensure that the 
level you choose correctly identifies all target files.

regards
  Steve
-- 
Steve Holden       +44 150 684 7255  +1 800 494 3119
Holden Web LLC/Ltd          http://www.holdenweb.com
Love me, love my blog  http://holdenweb.blogspot.com
Recent Ramblings     http://del.icio.us/steve.holden




More information about the Python-list mailing list