Je travaille actuellement sur le portage d'une application de python 2.7 à python 3.4.
Cependant, je rencontre actuellement un problème avec subprocess (du moins je pense que c'est la source) qui ne se comporte pas pareil en 2.7 et en 3.4.
Avant de passer au code problématique, je pense qu'il est important de vous donner un peu de contexte.
Il s'agit d'une application Flask dont le but est de fournir une interface web à un programme en ligne de commande.
Le programme en question dispose d'un mode "interactif" (une sorte de shell) duquel on peut envoyer des commandes sur stdin et lire le résultat sur stdout.
Mon application lance donc un subprocess en tâche de fond, et lui envoie des commandes sur stdin et lit les réponses sur stdout au besoin.
Le code qui nous intéresse est le suivant :
def _spawn_burp(self):
"""Launch the burp client process"""
cmd = [self.burpbin, '-c', self.burpconfcli, '-a', 'm']
self.proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False, universal_newlines=False)
# wait a little bit in case the process dies on a network timeout
time.sleep(0.5)
if not self._proc_is_alive():
raise Exception('Unable to spawn burp process')
_, w, _ = select([], [self.proc.stdin], [], 5)
if self.proc.stdin not in w:
self._logger('info', 'no no no no')
return
else:
self._logger('info', 'yes yes yes yes')
self.proc.stdin.write(b'j:pretty-print-off\n')
js = self._read_proc_stdout()
if self._is_warning(js):
self._logger('info', js['warning'])
def _proc_is_alive(self):
"""Check if the burp client process is still alive"""
if self.proc:
return self.proc.poll() == None
return False
def _read_proc_stdout(self):
"""reads the burp process stdout and returns a document or None"""
doc = u''
js = None
while True:
try:
if not self._proc_is_alive():
raise Exception('process died while reading its output')
r, _, _ = select([self.proc.stdout], [], [], 5)
if self.proc.stdout not in r:
raise TimeoutError('NOP')
else:
self._logger('info', 'YES')
doc += self.proc.stdout.readline().decode('UTF-8').rstrip('\n')
self._logger('info', doc)
js = self._is_valid_json(doc)
# if the string is a valid json and looks like a logline, we
# simply ignore it
self._logger('info', js)
if js and self._is_ignored(js):
self._logger('info', 'ICI')
doc = ''
continue
elif js:
break
except (TimeoutError, IOError, Exception) as e:
# the os throws an exception if there is no data or timeout
self._logger('warning', str(e))
break
return js
Avec python 2.7 je récupère bien différentes lignes alors qu'avec python 3.4, readline retourne la première ligne puis plus rien après.
Debug ici