2009-02-16 4 views
9

Vorrei utilizzare la versione di sottoprocesso di Python 2.6, perché consente la funzione Popen.terminate(), ma sono bloccato con Python 2.5. C'è un modo abbastanza pulito per utilizzare la versione più recente del modulo nel mio codice 2.5? Una specie di from __future__ import subprocess_module?Utilizzare il sottoprocesso Python 2.6 in Python 2.5

+1

Popen.terminate() non funziona in modo affidabile , Ho trovato. Stai attento. – Brandon

risposta

9

So che questa domanda ha già avuto risposta, ma per quello che vale, ho usato il subprocess.py fornito con Python 2.6 in Python 2.3 e ha funzionato bene. Se leggete i commenti nella parte superiore del file che dice:

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

+2

PEP 291 è molto utile sapere. Grazie! (link, per comodità degli altri: http://www.python.org/dev/peps/pep-0291/) Ho deciso che la tua risposta risponde alla mia domanda in modo più preciso, anche se gli zacherati sono anche molto utili. – xyz

+2

Avvertenza: questo non è proprio vero. L'implementazione del parametro close_fds nel modulo subprocess 2.6 utilizza os.closerange(), che è nuovo in python 2.6 – itsadok

+0

questo mi ha salvato la giornata! grazie :-) –

0

Bene Python è open source, sei libero di prendere quella funzione di pthread dalla 2.6 e spostarla nel tuo codice o usarla come riferimento per implementare la tua.

Per motivi che dovrebbero essere ovvi, non c'è modo di avere un ibrido di Python in grado di importare porzioni di versioni più recenti.

6

Non c'è davvero un ottimo modo per farlo. il sottoprocesso è implemented in python (in contrapposizione a C), quindi è possibile copiare il modulo da qualche parte e usarlo (sperando ovviamente che non usi nessuna bontà 2.6).

D'altra parte si potrebbe semplicemente implementare quali richieste di sottoprocesso fare e scrivere una funzione che invia SIGTERM su * nix e chiama TerminateProcess su Windows. La seguente applicazione è stata testata su Linux e in un Win XP VM, è necessario il 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) 

In questo modo si hanno solo a mantenere il codice terminate piuttosto che l'intero modulo.

+0

Fantastico, grazie mille! 'ps aux' mi dice che il processo è defunto dopo averlo terminato con questa funzione, ma sembra che os.waitpid (process.pid, 0) si prenda cura di questo. – xyz

2

Mentre questo non risponde direttamente alla tua domanda, potrebbe valerne la pena.

Le importazioni da __future__ cambiano in realtà solo le opzioni del compilatore, quindi mentre può trasformare in un'istruzione o fare in modo che le stringhe producano unicode anziché strs, non può modificare le funzionalità e le funzionalità dei moduli nella libreria standard Python.

+0

Capito, grazie. Non lo sapevo. – xyz

1

Ecco alcuni modi per terminare i processi su Windows, presi direttamente dal 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 seguito il suggerimento di Kamil Kisiel sull'utilizzo di python 2.6 subprocess.py in python 2.5 e ha funzionato perfettamente. Per semplificare, ho creato un pacchetto distutils che puoi installare easy_install e/o includere in buildout.

Per utilizzare il sottoprocesso da Python 2.6 in Python 2.5 progetto:

easy_install taras.python26 

nel codice

from taras.python26 import subprocess 

in buildout

[buildout] 
parts = subprocess26 

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