2009-02-16 8 views
9

Je voudrais utiliser la version de sous-processus de Python 2.6, car elle permet la fonction Popen.terminate(), mais je suis coincé avec Python 2.5. Existe-t-il une manière raisonnablement propre d'utiliser la version plus récente du module dans mon code 2.5? Une sorte de from __future__ import subprocess_module?Utiliser le module de sous-processus Python 2.6 en Python 2.5

+1

Popen.terminate() , J'ai trouvé. Faites attention. – Brandon

Répondre

9

Je sais que cette question a déjà été répondue, mais pour ce que ça vaut, j'ai utilisé le subprocess.py fourni avec Python 2.6 dans Python 2.3 et ça a bien fonctionné. Si vous lisez les commentaires au début du fichier, il dit:

# This module should remain compatible with Python 2.2, see PEP 291.

+2

PEP 291 est très utile à connaître. Merci! (lien, pour la commodité des autres: http://www.python.org/dev/peps/pep-0291/) J'ai décidé que votre réponse répondait à ma question plus précisément, même si les zacherates sont aussi très utiles. – xyz

+2

Avertissement: ce n'est pas tout à fait vrai. L'implémentation du paramètre close_fds dans le module de sous-processus 2.6 utilise os.closerange(), ce qui est nouveau dans python 2.6 – itsadok

+0

cela a sauvé ma journée! Je vous remercie :-) –

0

Bien Python est open source, vous êtes libre de prendre cette fonction pthread à partir de la version 2.6 et de la déplacer dans votre propre code ou de l'utiliser comme référence pour implémenter la vôtre.

Pour des raisons qui devraient être évidentes, il n'y a aucun moyen d'avoir un hybride de Python qui peut importer des parties de versions plus récentes.

6

Il n'y a pas vraiment un excellent moyen de le faire. sous-processus est implemented in python (par opposition à C) de sorte que vous pourriez éventuellement copier le module quelque part et l'utiliser (en espérant bien sûr qu'il n'utilise pas 2,6 bonté). D'autre part, vous pouvez simplement implémenter ce que les revendications de sous-processus à faire et écrire une fonction qui envoie SIGTERM sur * nix et appelle TerminateProcess sur Windows. La mise en œuvre suivante a été testé sur Linux et dans un Win XP vm, vous aurez besoin du python Windows extensions:

import sys 

def terminate(process): 
    """ 
    Kills a process, useful on 2.5 where subprocess.Popens don't have a 
    terminate method. 


    Used here because we're stuck on 2.5 and don't have Popen.terminate 
    goodness. 
    """ 

    def terminate_win(process): 
     import win32process 
     return win32process.TerminateProcess(process._handle, -1) 

    def terminate_nix(process): 
     import os 
     import signal 
     return os.kill(process.pid, signal.SIGTERM) 

    terminate_default = terminate_nix 

    handlers = { 
     "win32": terminate_win, 
     "linux2": terminate_nix 
    } 

    return handlers.get(sys.platform, terminate_default)(process) 

De cette façon, il suffit de maintenir le code terminate plutôt que l'ensemble du module.

+0

Génial, merci beaucoup! 'ps aux' me dit que le processus est terminé après l'avoir terminé avec cette fonction, mais il semble que os.waitpid (process.pid, 0) prenne cela en compte. – xyz

2

Bien que cela ne répond pas directement à votre question, il peut être utile de le savoir. En fait, les modifications apportées à __future__ ne modifient que les options du compilateur. Ainsi, même si les chaînes de caractères génèrent des unicodes au lieu des chaînes, elles ne peuvent pas modifier les capacités et les fonctionnalités des modules de la bibliothèque standard Python.

+0

J'ai compris, merci. Je ne le savais pas. – xyz

1

Voici quelques façons de mettre fin à des processus sous Windows, prises directement à partir http://code.activestate.com/recipes/347462/

# Create a process that won't end on its own 
import subprocess 
process = subprocess.Popen(['python.exe', '-c', 'while 1: pass']) 


# Kill the process using pywin32 
import win32api 
win32api.TerminateProcess(int(process._handle), -1) 


# Kill the process using ctypes 
import ctypes 
ctypes.windll.kernel32.TerminateProcess(int(process._handle), -1) 


# Kill the proces using pywin32 and pid 
import win32api 
PROCESS_TERMINATE = 1 
handle = win32api.OpenProcess(PROCESS_TERMINATE, False, process.pid) 
win32api.TerminateProcess(handle, -1) 
win32api.CloseHandle(handle) 


# Kill the proces using ctypes and pid 
import ctypes 
PROCESS_TERMINATE = 1 
handle = ctypes.windll.kernel32.OpenProcess(PROCESS_TERMINATE, False, process.pid) 
ctypes.windll.kernel32.TerminateProcess(handle, -1) 
ctypes.windll.kernel32.CloseHandle(handle) 
2

I a suivi la suggestion de Kamil Kisiel concernant l'utilisation de python 2.6 subprocess.py dans python 2.5 et cela a fonctionné parfaitement. Pour le rendre plus facile, j'ai créé un paquet distutils que vous pouvez easy_install et/ou inclure dans le buildout.

Pour utiliser le sous-processus de Python 2.6 en python 2.5 projet: ne fonctionne pas de manière fiable

easy_install taras.python26 

dans votre code

from taras.python26 import subprocess 

à buildout

[buildout] 
parts = subprocess26 

[subprocess26] 
recipe = zc.recipe.egg 
eggs = taras.python26