Gibt es eine Möglichkeit, den effektiven Prozessnamen in Python zu ändern?

78

Kann ich den effektiven Prozessnamen eines Python-Skripts ändern? Ich möchte einen anderen Namen anstelle des tatsächlichen Namens des Prozesses anzeigen, wenn ich die Systemprozessliste erhalte. In CI kann eingestellt werden

strcpy(argv[0],"othername");

Aber in Python

argv[0] = "othername"

scheint nicht zu funktionieren. Wenn ich eine Prozessliste bekomme (mit ps axin meiner Linux-Box), ändert sich der wirkliche Name nicht. Ich bevorzuge eine tragbare Lösung (oder eine Lösung für posix und eine andere für Windows-Umgebungen), falls vorhanden.

Danke im Voraus

Emilio
quelle
siehe auch superuser.com/questions/427642/... , wo bugs.python.org/issue5672 erwähnt wird
anarcat
Gibt es heutzutage eine Lösung für Windows? (Möglicherweise mit Python 3.x?) Genauer gesagt: Der "Windows Task-Manager" (STRG + UMSCHALT + ESCAPE), Registerkarte "Prozesse", sollte in der ersten Spalte "Bildname" eine benutzerdefinierte Zeichenfolge anzeigen und nicht nur python.exe oder pythonw.exe. NB: eine andere Lösung als das Duplizieren von python.exe zu mycustomstring.exe;)
Basj

Antworten:

13

Einfach gesagt, es gibt keinen tragbaren Weg. Sie müssen das System testen und die bevorzugte Methode für dieses System verwenden.

Außerdem bin ich verwirrt darüber, was Sie unter Prozessnamen unter Windows verstehen.

Meinen Sie einen Servicenamen? Ich nehme das an, weil nichts anderes wirklich Sinn macht (zumindest für mein Nicht-Windows-Gehirn).

In diesem Fall müssen Sie die WMI-Schnittstelle von Tim Golden verwenden und die .Change-Methode für den Dienst aufrufen ... zumindest gemäß seinem Tutorial .

Unter Linux funktionierte keine der Methoden, die ich gefunden habe, außer diesem schlecht gepackten Modul , das argv [0] für Sie festlegt.

Ich weiß nicht einmal, ob dies bei BSD-Varianten funktioniert (die einen Systemaufruf setproctitle haben). Ich bin mir ziemlich sicher, dass argv [0] unter Solaris nicht funktioniert.

Van Gale
quelle
Ich weiß, dass es spät ist, aber für neue Leser sollten Sie auch die Antwort @MattWritesCode in Betracht ziehen , die für CPython unter Linux schnell und einfach ist.
bufh
86

Ich habe kürzlich ein Python-Modul geschrieben, um den Prozesstitel auf tragbare Weise zu ändern: Überprüfen Sie https://github.com/dvarrazzo/py-setproctitle

Es ist ein Wrapper um den Code, der von PostgreSQL verwendet wird, um die Titeländerung durchzuführen. Es wird derzeit gegen Linux und Mac OS X getestet: Windows (mit eingeschränkter Funktionalität) und BSD-Portierungen sind unterwegs.

Bearbeiten: Ab Juli 2010 arbeitet das Modul mit BSD und mit eingeschränkter Funktionalität unter Windows und wurde auf Python 3.x portiert.

Piro
quelle
Kann nicht unter Windows installiert werden.
Benutzer
@user egal: es ist unter Windows nicht sehr hilfreich, aber es gibt nicht viel zu tun.
Piro
Gibt es eine Möglichkeit, die von ps -f angezeigten Argumente zu ändern? Der Programmname (immer Python) ist mir eigentlich egal, aber ich möchte die angezeigten Argumente ändern.
KillianDS
1
@ KillianDS: Meinst du, du willst die Ausgabe von "ps -f" anders als die von "ps"? Sie können es nicht afaik haben.
Piro
Das ist kein Python-Modul. Es ist ein C-Modul.
Bachsau
56

Eigentlich brauchst du 2 Dinge unter Linux: Ändern argv[0]von C(für ps auxfund Freunde) und Aufrufen prctlmit PR_SET_NAMEFlag.

Es gibt absolut keine Möglichkeit, das erste Stück aus Python selbst zu machen. Sie können den Prozessnamen jedoch einfach ändern, indem Sie prctl aufrufen.

def set_proc_name(newname):
    from ctypes import cdll, byref, create_string_buffer
    libc = cdll.LoadLibrary('libc.so.6')
    buff = create_string_buffer(len(newname)+1)
    buff.value = newname
    libc.prctl(15, byref(buff), 0, 0, 0)

def get_proc_name():
    from ctypes import cdll, byref, create_string_buffer
    libc = cdll.LoadLibrary('libc.so.6')
    buff = create_string_buffer(128)
    # 16 == PR_GET_NAME from <linux/prctl.h>
    libc.prctl(16, byref(buff), 0, 0, 0)
    return buff.value

import sys
# sys.argv[0] == 'python'

# outputs 'python'
get_proc_name()

set_proc_name('testing yeah')

# outputs 'testing yeah'
get_proc_name()

ps auxfzeigt danach nur noch 'Python' an :(. Aber topund ps -Azeigt den neuen Prozessnamen 'testing yeah' an :). Auch killallund pkillwird mit neuem Namen arbeiten.

Übrigens ändert sich auch der Procname von Google Code argv[0]und damit sogar die ps auxfAusgabe.

UPDATE : Die in dieser Antwort veröffentlichte Lösung funktioniert unter FreeBSD manchmal nicht gut. Ich verwende jetzt py-setproctitle , das in dieser Antwort angegeben ist, für ungefähr ein Jahr auf verschiedenen Linux- und Freebsd-Boxen. Nein scheitert bisher! Jeder sollte auch! :). Er verwendet fast den gleichen Code wie PostgreSQL verwendet in seiner Hauptdatenbank und Kindprozesse.

Vadim Fint
quelle
procname funktioniert nicht auf PyPy (nur auf CPython) muss setproctitle verwenden.
Radtek
12

Schauen Sie sich das setproctitle- Paket an

Dies ist eine ziemlich tragbare Version und funktioniert auf vielen Plattformen.

pip install setproctitle

 

import setproctitle

setproctitle.setproctitle('new proc title as seen in top')
Valgog
quelle
1
Schöne einfache Lösung hier.
David Parks
4

Erstens bin ich mir nicht sicher, ob einfache Einstellungen argv[0]in einem C-Programm den Namen in ändern ps. Vielleicht tut es in einigen Unixen, aber ich verstehe, dass es nicht erwartet wird.

Zweitens, da Windows speziell nicht POSIX-kompatibel ist, sind nur wenige Dinge zwischen POSIX und Nicht-POSIX "portabel". Da Sie ausdrücklich "ps" sagen, gehe ich davon aus, dass POSIX Ihre Priorität ist und Windows möglicherweise nicht funktioniert.

Noch wichtiger ist, dass ich verstehe, argv[0]dass Änderungen erforderlich sind exec, um diese Änderungen vorzunehmen. Insbesondere hat der execAufruf sowohl einen Pfad zu einer ausführbaren Datei als auch eine separate argvListe. Wenn Sie Ihren eigenen Anruf tätigen, können Sie die Shell-Konvention zum Einfügen des ausführbaren Namens brechen argv[0].

Sie verfügen über eine Prozessverwaltung für die Betriebssystembibliothek, mit der Sie direkt auf die Betriebssystembibliothek zugreifen können. Sie sollten in Betracht ziehen, Ihr Skript in zwei Teile zu teilen - einen Starter und die "echte Arbeit". Der Starter legt die Laufzeitumgebung fest und führt die eigentliche Arbeit mit den gewünschten Parametern aus.

In C ersetzen Sie Ihren eigenen Prozess durch einen anderen. In Python ersetzen Sie den alten Python-Interpreter durch einen neuen mit einem anderen Argument [0]. Hoffentlich wird es das nicht verhindern. Einige Programme überprüfen argv [0], um zu entscheiden, was sie tun.

Sie haben auch subprocess.popen , mit dem Sie die gewünschten Argumente und die ausführbare Datei festlegen können. In diesem Fall sollte der übergeordnete Prozess jedoch verweilen, um das Kind zu sammeln, wenn das Kind fertig ist. Der Elternteil darf nicht mehr als a tunPopen.wait

S.Lott
quelle
1
Nein, das Ändern von argv unter Linux (und wahrscheinlich auch unter anderen Unixen, aber nicht allen) ändert sofort den sichtbaren Prozessnamen, der von vielen weit verbreiteten Programmen verwendet wird, um beschreibende Namen für ihre Prozesse anzugeben: sowohl ssh als auch postgres tun dies und einige Ändern Sie aktiv ihren Namen im laufenden Betrieb, um ihren aktuellen Status anzuzeigen. Dazu könnte mithilfe des API-Aufrufs Py_GetArgcArgv ein Python-Modul geschrieben werden.
Glenn Maynard
3

Meine Antwort auf eine ähnliche Frage, die als Duplikat markiert ist :

Es ist einfacher (Sie müssen keine Bibliotheken importieren), aber vielleicht nicht so elegant. Sie müssen "env" nicht innerhalb der Shebang-Linie verwenden.

Mit anderen Worten, dies wird in der Prozessliste als "Python" bezeichnet:

#!/usr/bin/env python

Dies wird jedoch mit Ihrem Skriptnamen benannt:

#!/usr/bin/python

So können Sie es mit so etwas wie pidof -x scriptnameoder findenps -C scriptname

Sasha Ru
quelle
2

Ich habe festgestellt, dass Python-Prctl unter Linux sehr gut funktioniert. Sie müssen etwas anderes für Windows finden.

Vukasin Toroman
quelle
-17
In [1]: import sys

In [2]: print sys.argv[0]
C:\Python25\scripts\ipython.py

In [3]: sys.argv[0] = 'foo'

In [4]: print sys.argv[0]
foo

Beachten Sie das einzelne '=' Zeichen

Boris Gorelik
quelle
3
Aber wenn ich ps (Prozessliste in Linux-Boxen) ausführe, bleibt der Prozessname genau gleich. Versuchen Sie
Emilio
10
Dies ändert den Prozessnamen überhaupt nicht. Es ändert nur Pythons Kopie von argv. Ich würde empfehlen, diese offensichtlich falsche Antwort zu löschen.
Dakkaron