Funktion ueberschreiben?

2 views
Skip to first unread message

Ulli Horlacher

unread,
Dec 3, 2022, 3:28:20 AM12/3/22
to
Ich teste gerade duply/duplicity.
U.a. stoert mich da Ausgabe des Datums in US Format, zB:

Last full backup date: Tue Nov 29 17:38:31 2022
Fri Dec 2 09:08:31 2022 .

Ich hab auch schon die Stelle gefunden, wo das passiert:

/usr/lib/python3/dist-packages/duplicity/dup_time.py

def timetopretty(timeinseconds):
u"""Return pretty version of time"""
return time.asctime(time.localtime(timeinseconds))


Ist also hard coded und nicht User konfigurierbar.

Ich hab nun die letzte Zeile ersetzt durch:

return time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(timeinseconds))


Damit bekomme ich brauchbares ISO Datumsformat:

Last full backup date: 2022-11-29 17:38:31
2022-12-02 09:08:31 .

ABER: duplicity ist ein Ubuntu-Paket und beim naechstes (automatischen)
Update wird mein modifiziertes dup_time.py ersetzt.
Irgendwelche Aenderungen des Original-Codes verbieten sich also.

Meine Idee nun:

Ich schreibe einen wrapper fuer duplicity, der time.asctime() durch meine
obige Funktion ersetzt. So wuerde ich das zumindest bei C oder Perl machen.

(Wie) geht das bei Python?

Oder anderer, besserer Vorschlag?


--
Ullrich Horlacher Server und Virtualisierung
Rechenzentrum TIK
Universitaet Stuttgart E-Mail: horl...@tik.uni-stuttgart.de
Allmandring 30a Tel: ++49-711-68565868
70569 Stuttgart (Germany) WWW: http://www.tik.uni-stuttgart.de/

Mike Müller

unread,
Dec 3, 2022, 4:00:37 AM12/3/22
to
Am 03.12.22 um 09:28 schrieb Ulli Horlacher:
> Ich teste gerade duply/duplicity.
> U.a. stoert mich da Ausgabe des Datums in US Format, zB:
>
> Last full backup date: Tue Nov 29 17:38:31 2022
> Fri Dec 2 09:08:31 2022 .
>
> Ich hab auch schon die Stelle gefunden, wo das passiert:
>
> /usr/lib/python3/dist-packages/duplicity/dup_time.py
>
> def timetopretty(timeinseconds):
> u"""Return pretty version of time"""
> return time.asctime(time.localtime(timeinseconds))
>
>
> Ist also hard coded und nicht User konfigurierbar.
>
> Ich hab nun die letzte Zeile ersetzt durch:
>
> return time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(timeinseconds))
>
>
> Damit bekomme ich brauchbares ISO Datumsformat:
>
> Last full backup date: 2022-11-29 17:38:31
> 2022-12-02 09:08:31 .
>
> ABER: duplicity ist ein Ubuntu-Paket und beim naechstes (automatischen)
> Update wird mein modifiziertes dup_time.py ersetzt.
> Irgendwelche Aenderungen des Original-Codes verbieten sich also.
>
> Meine Idee nun:
>
> Ich schreibe einen wrapper fuer duplicity, der time.asctime() durch meine
> obige Funktion ersetzt. So wuerde ich das zumindest bei C oder Perl machen.
>
> (Wie) geht das bei Python?

import duplicity.dup_time

def timetopretty(timeinseconds):
"""Return pretty version of time"""
return time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(timeinseconds))

duplicity.dup_time.timetopretty = timetopretty

ganz zu Beginn des Programms sollte funktionieren. Wichtig ist, dass
duplicity.dup_time nicht schon vorher importiert wird. Sonst müsstest du es
vorher aus sys.modules entfernen.

Viele Grüße
Mike

Mike Müller

unread,
Dec 3, 2022, 7:49:58 AM12/3/22
to
Am 03.12.22 um 10:53 schrieb Stefan Ram:
> =?UTF-8?Q?Mike_M=c3=bcller?= <mmue...@python-academy.de> writes:
>> import duplicity.dup_time
>> def timetopretty(timeinseconds):
>> """Return pretty version of time"""
>> return time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(timeinseconds))
>> duplicity.dup_time.timetopretty = timetopretty
>> ganz zu Beginn des Programms sollte funktionieren. Wichtig ist, dass
>> duplicity.dup_time nicht schon vorher importiert wird. Sonst müsstest du es
>> vorher aus sys.modules entfernen.
>
> Diese Einschränkung verstehe ich nicht ganz. Ich dachte, daß sich
> das "monkey patching" ab dem Zeitpunkt seiner Ausführung auswirkt.
> In Deinem Beispiel wird doch auch "schon vorher importiert", also
> als erstes importiert, dann gepatcht, und ab da wirkt es. Vergleiche:

Du hast Recht. Diese Einschränkung bezieht sich nur auf das Ändern des
Quelltext in einem Modul und einen folgenden Neu-Import der Datei im laufenden
Prozess. Da du dem Namen eine neue Funktion zuweist, müsste es ab diesem
Zeitpunkt überall im Programm wirksam sein. Das mit dem Löschen aus
sys.modules ist nur beim Entwickeln z.B. in Notebooks wichtig, wenn man den
Code in einem Modul ändert und dann neu importiert ohne das Notebook neu zu
starten.

> import tkinter.messagebox
> tkinter.messagebox.showinfo( "arg", "arg1" )
> tkinter.messagebox.showinfo = print
> tkinter.messagebox.showinfo( "arg", "arg1" )
>
> .
>
> _______________________________________________
> python-de Mailingliste -- pyth...@python.org
> Zur Abmeldung von dieser Mailingliste senden Sie eine Nachricht an python-...@python.org
> https://mail.python.org/mailman3/lists/python-de.python.org/
> Mitgliedsadresse: mmue...@python-academy.de

Peter J. Holzer

unread,
Dec 3, 2022, 8:27:10 AM12/3/22
to
On 2022-12-03 09:53, Stefan Ram <r...@zedat.fu-berlin.de> wrote:
>=?UTF-8?Q?Mike_M=c3=bcller?= <mmue...@python-academy.de> writes:
>>import duplicity.dup_time
>>def timetopretty(timeinseconds):
>> """Return pretty version of time"""
>> return time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(timeinseconds))
>>duplicity.dup_time.timetopretty = timetopretty
>>ganz zu Beginn des Programms sollte funktionieren. Wichtig ist, dass
>>duplicity.dup_time nicht schon vorher importiert wird. Sonst müsstest du es
>>vorher aus sys.modules entfernen.
>
> Diese Einschränkung verstehe ich nicht ganz. Ich dachte, daß sich
> das "monkey patching" ab dem Zeitpunkt seiner Ausführung auswirkt.

Das kommt darauf an, was importiert wird.

Nach einem
import duplicity.dup_time
referenziert duplicity.dup_time.timetopretty das Objekt, auf das die
Variable timetopretty in dup_time gerade verweist, und wenn die geändert
wird, hat das den offensichtlichen Effekt

Aber mit
from duplicity.dup_time import timetopretty
wird eine neue lokale Variable timetopretty angelegt, die auf das Objekt
zu diesem Zeitpunkt verweist. Wenn man später
duplicity.dup_time.timetopretty ändert, zeigt das lokale timetopretty
immer noch auf das ursprüngliche Objekt.

hp

Ulli Horlacher

unread,
Dec 3, 2022, 10:46:34 AM12/3/22
to
Mike Müller <mmue...@python-academy.de> wrote:

>> ABER: duplicity ist ein Ubuntu-Paket und beim naechstes (automatischen)
>> Update wird mein modifiziertes dup_time.py ersetzt.
>> Irgendwelche Aenderungen des Original-Codes verbieten sich also.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>
>> Meine Idee nun:
>>
>> Ich schreibe einen wrapper fuer duplicity, der time.asctime() durch meine
>> obige Funktion ersetzt. So wuerde ich das zumindest bei C oder Perl machen.
>>
>> (Wie) geht das bei Python?
>
> import duplicity.dup_time
>
> def timetopretty(timeinseconds):
> """Return pretty version of time"""
> return time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(timeinseconds))
>
> duplicity.dup_time.timetopretty = timetopretty
>
> ganz zu Beginn des Programms sollte funktionieren.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Funktioniert so nicht!

Ich kann/will/darf das Original-Programm nicht veraendern!

Christopher Arndt

unread,
Dec 3, 2022, 11:04:06 AM12/3/22
to
Am 03.12.22 um 16:46 schrieb Ulli Horlacher:
> Funktioniert so nicht!
>
> Ich kann/will/darf das Original-Programm nicht veraendern!

Die dem Geist der Open Source Idee entsprechende, karmastärkende
Vorgehensweise wäre, einen Patch mit deiner ersten Lösung Upstream
einzureichen:

https://gitlab.com/duplicity/duplicity

(...und dann ca. ein Jahrzehnt zu warten, bis dein Change in den
debian/Ubuntu Package-Repos angekommen ist.)

:-)


Chris

Ulli Horlacher

unread,
Dec 3, 2022, 11:56:39 AM12/3/22
to
Und der Gnade der Maintainer ausgeliefert zu sein, ob sie meinen
Patch ueberhaupt akzeptieren.
Vorher bin ich in Rente!

Deshalb zurueck auf LOS: gibts bei Python keine Moeglichkeit VORAB eine
andere Library unterzuschieben?

Mit C, Perl, etc geht das.

Peter J. Holzer

unread,
Dec 3, 2022, 7:11:41 PM12/3/22
to
On 2022-12-03 16:56, Ulli Horlacher <fram...@rus.uni-stuttgart.de> wrote:
> Deshalb zurueck auf LOS: gibts bei Python keine Moeglichkeit VORAB eine
> andere Library unterzuschieben?

Nicht, dass ich wüsste, aber ich wüsste auch nicht, wie das bei Perl
gehen soll - vielleicht missverstehe ich, was Du mit "VORAB
unterzuschieben" meinst.

Du kannst natürlich PYTHONPATH setzen. Aber mir scheint, die gleichen
Gründe, die ein Ändern des Scripts ausschließen, würden das auch
ausschließen.

hp

Ulli Horlacher

unread,
Dec 4, 2022, 4:59:56 AM12/4/22
to
Peter J. Holzer <hjp-u...@hjp.at> wrote:
> On 2022-12-03 16:56, Ulli Horlacher <fram...@rus.uni-stuttgart.de> wrote:
>> Deshalb zurueck auf LOS: gibts bei Python keine Moeglichkeit VORAB eine
>> andere Library unterzuschieben?
>
> Nicht, dass ich wüsste, aber ich wüsste auch nicht, wie das bei Perl
> gehen soll

Via environment Variable PERLLIB, analog zu LD_LIBRARY_PATH.


> Du kannst natürlich PYTHONPATH setzen.

Wir kommen der Sache naeher :-)

/usr/lib/python3/dist-packages/duplicity/dup_time.py verwendet

import time

Um time.asctime() zu ersetzen muesste ich also die Standard time
Bibliothek durch meine ersetzen und da time.asctime() passend umschreiben?

Leider finde ich kein time.py, wo versteckt sich das Python time Modul?

Peter J. Holzer

unread,
Dec 4, 2022, 7:49:56 AM12/4/22
to
On 2022-12-04 09:59, Ulli Horlacher <fram...@rus.uni-stuttgart.de> wrote:
> Peter J. Holzer <hjp-u...@hjp.at> wrote:
>> On 2022-12-03 16:56, Ulli Horlacher <fram...@rus.uni-stuttgart.de> wrote:
>>> Deshalb zurueck auf LOS: gibts bei Python keine Moeglichkeit VORAB eine
>>> andere Library unterzuschieben?
>>
>> Nicht, dass ich wüsste, aber ich wüsste auch nicht, wie das bei Perl
>> gehen soll
>
> Via environment Variable PERLLIB, analog zu LD_LIBRARY_PATH.

Beides beeinflusst nur, wo Libraries gesucht werden. Es lädt nicht vorab
eine Library. Ich dachte, Du meinst sowas wie LD_PRELOAD (wobei auch das
die Definition von "vorab" etwas dehnt).


>> Du kannst natürlich PYTHONPATH setzen.
>
> Wir kommen der Sache naeher :-)
>
> /usr/lib/python3/dist-packages/duplicity/dup_time.py verwendet
>
> import time
>
> Um time.asctime() zu ersetzen muesste ich also die Standard time
> Bibliothek durch meine ersetzen und da time.asctime() passend umschreiben?
>
> Leider finde ich kein time.py, wo versteckt sich das Python time Modul?
>

Laut strace löst ein »import time« keinen Filesystem-Zugriff aus, das
Modul dürfte also wohl im Python-Binary eingebaut sein.

Aber time zu ersetzen scheint mir sowieso keine zielführende Taktik zu
sein. Asctime ist ja nicht die einzige Funktion aus diesem Modul, die
verwendet wird. Wie ersetzt Du den Rest?

Wenn Du ein Modul ersetzen willst, dann eher duplicity.dup_time. Das
enthält erstens die Funktion, deren Verhalten Du ändern willst, und
zweitens ist das überschaubarer Python-Code in der Applikation und nicht
ein Python-Core-Modul, das vermutlich an zig anderen Stellen verwendet
wird, an die Du nicht denkst.

Für Monkeypatching müsstest Du eine *andere* Library finden, die zwar
geladen aber nicht verwendet wird (aber warum sollte sie dann geladen
werden), oder deren verwendete Funktionalität so trivial ist, dass sie
leicht ersetzbar ist.

Wenn mich das Datumsformat ausreichend stören würde, würde ich das
Debian-Paket patchen (ich gehe mal davon aus, dass Du das auf mehr als
einem System haben willst). Das ist wahrscheinlich am einfachsten und
saubersten.

Peter J. Holzer

unread,
Dec 4, 2022, 8:06:08 AM12/4/22
to
On 2022-12-04 12:49, Peter J. Holzer <hjp-u...@hjp.at> wrote:
> On 2022-12-04 09:59, Ulli Horlacher <fram...@rus.uni-stuttgart.de> wrote:
>> Peter J. Holzer <hjp-u...@hjp.at> wrote:
>>> On 2022-12-03 16:56, Ulli Horlacher <fram...@rus.uni-stuttgart.de> wrote:
>>>> Deshalb zurueck auf LOS: gibts bei Python keine Moeglichkeit VORAB eine
>>>> andere Library unterzuschieben?
>>>
>>> Nicht, dass ich wüsste, aber ich wüsste auch nicht, wie das bei Perl
>>> gehen soll
>>
>> Via environment Variable PERLLIB, analog zu LD_LIBRARY_PATH.
>
> Beides beeinflusst nur, wo Libraries gesucht werden. Es lädt nicht vorab
> eine Library. Ich dachte, Du meinst sowas wie LD_PRELOAD (wobei auch das
> die Definition von "vorab" etwas dehnt).

Vergessen, dazuzuschreiben: Du könntest natürlich LD_PRELOAD azu
verwenden, asctime in der libc zu ersetzen. Maximaler Blast-Radius :-).

hp

Ulli Horlacher

unread,
Dec 4, 2022, 8:10:04 AM12/4/22
to
Peter J. Holzer <hjp-u...@hjp.at> wrote:

>> Via environment Variable PERLLIB, analog zu LD_LIBRARY_PATH.
>
> Beides beeinflusst nur, wo Libraries gesucht werden.

Genau das reicht doch: es soll meine modifizierte time Library gefunden
und dann zur Laufzeit geladen werden.


>>> Du kannst natürlich PYTHONPATH setzen.
>>
>> Wir kommen der Sache naeher :-)
>>
>> /usr/lib/python3/dist-packages/duplicity/dup_time.py verwendet
>>
>> import time
>>
>> Um time.asctime() zu ersetzen muesste ich also die Standard time
>> Bibliothek durch meine ersetzen und da time.asctime() passend umschreiben?
>>
>> Leider finde ich kein time.py, wo versteckt sich das Python time Modul?
>>
>
> Laut strace löst ein »import time« keinen Filesystem-Zugriff aus, das
> Modul dürfte also wohl im Python-Binary eingebaut sein.

Bloed, dann kann ich es wohl nicht ersetzen.


> Aber time zu ersetzen scheint mir sowieso keine zielführende Taktik zu
> sein. Asctime ist ja nicht die einzige Funktion aus diesem Modul, die
> verwendet wird. Wie ersetzt Du den Rest?

Gar nicht. Die bleibt gleich.
Ich wollte time.py kopieren und da drin nur time.asctime() modifizieren.
Da es das aber gar nicht als eigenes library-file gibt, ist diese Idee nicht
umsetzbar. Sackgasse.


> Wenn Du ein Modul ersetzen willst, dann eher duplicity.dup_time.

Da stecken halt noch viel mehr Funktionen drin. Wenn es nun ein
Ubuntu-Update davon gibt, kann es zu Inkompatibiltaeten kommen.

In Perl kann man folgendes machen:
Ein Modul laden und danach nur eine Funktion nachtraeglich ersetzen.
Geht so was auch mit Python?
Dann wuerde ich das original duplicity.dup_time laden und dann
timetopretty() neu definieren. Kann ich dazu PYTHONPATH verwenden?


> Wenn mich das Datumsformat ausreichend stören würde, würde ich das
> Debian-Paket patchen (ich gehe mal davon aus, dass Du das auf mehr als
> einem System haben willst). Das ist wahrscheinlich am einfachsten und
> saubersten.

Nicht machbar. Die Zielsysteme koennen auch Redhat sein und ich hab da
auch keine root-Rechte.

Peter J. Holzer

unread,
Dec 4, 2022, 8:46:55 AM12/4/22
to
On 2022-12-04 13:10, Ulli Horlacher <fram...@rus.uni-stuttgart.de> wrote:
> Peter J. Holzer <hjp-u...@hjp.at> wrote:
>
>>> Via environment Variable PERLLIB, analog zu LD_LIBRARY_PATH.
>>
>> Beides beeinflusst nur, wo Libraries gesucht werden.
>
> Genau das reicht doch: es soll meine modifizierte time Library gefunden
> und dann zur Laufzeit geladen werden.

Vielleicht, aber das war nicht Deine Frage.

>> Aber time zu ersetzen scheint mir sowieso keine zielführende Taktik zu
>> sein. Asctime ist ja nicht die einzige Funktion aus diesem Modul, die
>> verwendet wird. Wie ersetzt Du den Rest?
>
> Gar nicht. Die bleibt gleich.
> Ich wollte time.py kopieren und da drin nur time.asctime() modifizieren.
> Da es das aber gar nicht als eigenes library-file gibt, ist diese Idee nicht
> umsetzbar. Sackgasse.
>
>
>> Wenn Du ein Modul ersetzen willst, dann eher duplicity.dup_time.
>
> Da stecken halt noch viel mehr Funktionen drin.

12 Funktionen und eine Klasse. Das Modul »time« hat ungefähr das
Doppelte. Und ein guter Teil davon ist notwendigerweise in C
geschrieben. Das scheint mir jedenfalls deutlich komplexer zu sein, als
das ziemlich übersichtliche dup_time.

> Wenn es nun ein Ubuntu-Update davon gibt, kann es zu
> Inkompatibiltaeten kommen.

Für das hypothetische python.py gilt das genauso.

> In Perl kann man folgendes machen: Ein Modul laden und danach nur eine
> Funktion nachtraeglich ersetzen. Geht so was auch mit Python?

Ja, wurde ja schon erklärt. Aber die Stelle, wo das trivial möglich
wäre, willst Du ja nicht angreifen.

(Was für mich auch eher schleierhaft macht. wie du da ein Wrapper-Script
unterbringen willst: Würden nicht alle Argumente, die gegen eine
Modifikation des Originalscripts sprechen auch gegen ein Wrapper-Script
sprechen? Bzw. Wie stellst Du sicher, dass das Wrapper-Script aufgerufen
wird, wenn es woanders liegt?)

> Dann wuerde ich das original duplicity.dup_time laden und dann
> timetopretty() neu definieren. Kann ich dazu PYTHONPATH verwenden?

Nicht direkt. Wie in meinem vorigen Posting beschrieben, vielleicht
indirekt, aber das ist mindestens so fragil.

Wenn Du ein *anderes* Script aufrufen kannst, ist es wahrscheinlich am
einfachsten, das Originalscript mittels exec aufzurufen:

% cat foo
#!/usr/bin/python3

import time

timeinseconds = time.time()
print(time.asctime(time.localtime(timeinseconds)))
% ./foo
Sun Dec 4 14:39:06 2022
% cat foo_wrapper
#!/usr/bin/python3

import time

def my_asctime(tm):
return "Gotcha!"

time.asctime = my_asctime

with open("foo") as f:
code = f.read()
exec(code)
% ./foo_wrapper
Gotcha!


>> Wenn mich das Datumsformat ausreichend stören würde, würde ich das
>> Debian-Paket patchen (ich gehe mal davon aus, dass Du das auf mehr als
>> einem System haben willst). Das ist wahrscheinlich am einfachsten und
>> saubersten.
>
> Nicht machbar. Die Zielsysteme koennen auch Redhat sein und ich hab da
> auch keine root-Rechte.

Was mich wieder zu der Frage zurückführt, wie Du da ein Wrapper-Script
installieren willst.

hp

Ulli Horlacher

unread,
Dec 4, 2022, 9:41:07 AM12/4/22
to
Peter J. Holzer <hjp-u...@hjp.at> wrote:

>> Genau das reicht doch: es soll meine modifizierte time Library gefunden
>> und dann zur Laufzeit geladen werden.
>
> Vielleicht, aber das war nicht Deine Frage.

Meine Frage war mehrteilig, inklusive der nach Alternativloesungen :-)


>> In Perl kann man folgendes machen: Ein Modul laden und danach nur eine
>> Funktion nachtraeglich ersetzen. Geht so was auch mit Python?
>
> Ja, wurde ja schon erklärt.

Nicht konkret genug.

Im duplicity source code steht an mehreren Stellen:

from duplicity import dup_time


Angenommen mein modifiziertes dup_time.py liegt in
/opt/duply/lib/dup_time.py

Was muss dann in $PYTHONPATH stehen, damit das geladen wird.
Und was muss ich in /opt/duply/lib/dup_time.py schreiben um
/usr/lib/python3/dist-packages/duplicity/dup_time.py
zu laden?



> (Was für mich auch eher schleierhaft macht. wie du da ein Wrapper-Script
> unterbringen willst

Trivial: das steht irgendwo in $PATH weiter vorne.
So was hab ich schon oft gemacht bei anderen Sprachen.



> Wenn Du ein *anderes* Script aufrufen kannst, ist es wahrscheinlich am
> einfachsten, das Originalscript mittels exec aufzurufen:
>
> % cat foo
> #!/usr/bin/python3
>
> import time
>
> timeinseconds = time.time()
> print(time.asctime(time.localtime(timeinseconds)))
> % ./foo
> Sun Dec 4 14:39:06 2022
> % cat foo_wrapper
> #!/usr/bin/python3
>
> import time
>
> def my_asctime(tm):
> return "Gotcha!"
>
> time.asctime = my_asctime
>
> with open("foo") as f:
> code = f.read()
> exec(code)
> % ./foo_wrapper
> Gotcha!

"foo" waere dann "/usr/bin/duplicity" ?
Aber da steht doch drin:
import time
was mir meine grad modifizierte time.asctime() Funktion wieder ueberschreibt?


>>> Wenn mich das Datumsformat ausreichend stören würde, würde ich das
>>> Debian-Paket patchen (ich gehe mal davon aus, dass Du das auf mehr als
>>> einem System haben willst). Das ist wahrscheinlich am einfachsten und
>>> saubersten.
>>
>> Nicht machbar. Die Zielsysteme koennen auch Redhat sein und ich hab da
>> auch keine root-Rechte.
>
> Was mich wieder zu der Frage zurückführt, wie Du da ein Wrapper-Script
> installieren willst.

$HOME/bin, /var/tmp/bin, etc

Peter J. Holzer

unread,
Dec 4, 2022, 4:07:30 PM12/4/22
to
On 2022-12-04 14:41, Ulli Horlacher <fram...@rus.uni-stuttgart.de> wrote:
> Peter J. Holzer <hjp-u...@hjp.at> wrote:
>>> In Perl kann man folgendes machen: Ein Modul laden und danach nur eine
>>> Funktion nachtraeglich ersetzen. Geht so was auch mit Python?
>>
>> Ja, wurde ja schon erklärt.
>
> Nicht konkret genug.
>
> Im duplicity source code steht an mehreren Stellen:
>
> from duplicity import dup_time
>
>
> Angenommen mein modifiziertes dup_time.py liegt in
> /opt/duply/lib/dup_time.py
>
> Was muss dann in $PYTHONPATH stehen, damit das geladen wird.

So geht das gar nicht, weil Du mit
from duplicity import dup_time
ja etwas laden willst, das innerhalb von "duplicity" ist. Das muss also
schon auch vorkommen:

/opt/duply/lib
└── duplicity
├── __init__.py
└── dup_time.py

export PYTHONPATH=/opt/duply/lib

Das File __init__.py kann leer sein, aber es muss existieren, damit from
duplicity import ... funktioniert.

> Und was muss ich in /opt/duply/lib/dup_time.py schreiben um

Nach /opt darfst Du schreiben?

> /usr/lib/python3/dist-packages/duplicity/dup_time.py
> zu laden?

Das würde ich nicht machen. Dein duplicity/dup_time.py ersetzt das
systemweite. Eventuell kannst Du das File lesen und mit exec ausführen,
so wie ich es unten mit dem Script gemacht habe.

>> (Was für mich auch eher schleierhaft macht. wie du da ein Wrapper-Script
>> unterbringen willst
>
> Trivial: das steht irgendwo in $PATH weiter vorne.
> So was hab ich schon oft gemacht bei anderen Sprachen.

Geht es da eigentlich nur um dich oder um alle User des Systems? Ich bin
davon ausgegangen, dass letzteres der Fall ist. Aber wenn Du nicht Root
bist, solltest Du nichts machen können, was die Funktionalität anderer
User beeinflusst. Also irgendwie ist mir nicht klar, welche Rolle Du da
spielst und was eigentlich das Ziel ist.


>> % cat foo_wrapper
>> #!/usr/bin/python3
>>
>> import time
>>
>> def my_asctime(tm):
>> return "Gotcha!"
>>
>> time.asctime = my_asctime
>>
>> with open("foo") as f:
>> code = f.read()
>> exec(code)
>> % ./foo_wrapper
>> Gotcha!
>
> "foo" waere dann "/usr/bin/duplicity" ?

Ja.

> Aber da steht doch drin:
> import time
> was mir meine grad modifizierte time.asctime() Funktion wieder ueberschreibt?

Nein. "import" funktioniert ähnlich wie "use" in Perl. Wenn ein Modul
schon importiert wurde, wird es kein zweites Mal importiert.

>> Was mich wieder zu der Frage zurückführt, wie Du da ein Wrapper-Script
>> installieren willst.
>
> $HOME/bin, /var/tmp/bin, etc

D.h. du willst das nur für dich, nicht für die anderen User des Systems?
(Dass Du oben /opt erwähnst, widerspricht dem etwas)

hp

Ulli Horlacher

unread,
Dec 5, 2022, 3:07:23 AM12/5/22
to
Peter J. Holzer <hjp-u...@hjp.at> wrote:

>>> % cat foo_wrapper
>>> #!/usr/bin/python3
>>>
>>> import time
>>>
>>> def my_asctime(tm):
>>> return "Gotcha!"
>>>
>>> time.asctime = my_asctime
>>>
>>> with open("foo") as f:
>>> code = f.read()
>>> exec(code)
>>> % ./foo_wrapper
>>> Gotcha!
>>
>> "foo" waere dann "/usr/bin/duplicity" ?
>
> Ja.
>
>> Aber da steht doch drin:
>> import time
>> was mir meine grad modifizierte time.asctime() Funktion wieder ueberschreibt?
>
> Nein. "import" funktioniert ähnlich wie "use" in Perl. Wenn ein Modul
> schon importiert wurde, wird es kein zweites Mal importiert.

Ahh... sehr gut. Wieder was gelernt :-)

Prinzipiell gefaellt mir dieser Ansatz, aber ich hab wohl noch was falsch
gemacht (duply ruft duplicity auf):

root@obertux:/opt/s3tik/bin# type -a duplicity
duplicity is /opt/s3tik/bin/duplicity
duplicity is /usr/bin/duplicity

root@obertux:/opt/s3tik/bin# duply root list
Start duply v2.2, time is 2022-12-05 08:57:09.
Using profile '/root/.duply/root'.
Using installed duplicity version 0.8.12, python 3.8.10 (/usr/bin/python3), gpg 2.2.19 (Home: /root/.gnupg), awk 'mawk 1.3.4 20200120', grep 'grep (GNU grep) 3.4', bash '5.0.17(1)-release (x86_64-pc-linux-gnu)'.
Checking TEMP_DIR '/tmp' is a folder and writable (OK)
Test - En/Decryption skipped. (GPG disabled)

--- Start running command LIST at 08:57:10.534 ---
Traceback (innermost last):
File "<string>", line 106, in <module>
File "<string>", line 92, in with_tempdir
File "/usr/lib/python3/dist-packages/duplicity/dup_main.py", line 1538, in main
do_backup(action)
File "/usr/lib/python3/dist-packages/duplicity/dup_main.py", line 1558, in do_backup
col_stats = dup_collections.CollectionsStatus(globals.backend,
File "/usr/lib/python3/dist-packages/duplicity/dup_collections.py", line 744, in set_values
self.get_backup_chains(partials + backend_filename_list)
File "/usr/lib/python3/dist-packages/duplicity/dup_collections.py", line 896, in get_backup_chains
add_to_chains(s)
File "/usr/lib/python3/dist-packages/duplicity/dup_collections.py", line 884, in add_to_chains
log.Debug(_(u"Found backup chain %s") % (new_chain.short_desc()))
File "/usr/lib/python3/dist-packages/duplicity/dup_collections.py", line 408, in short_desc
return u"[%s]-[%s]" % (dup_time.timetopretty(self.start_time),
File "/usr/lib/python3/dist-packages/duplicity/dup_time.py", line 169, in timetopretty
return time.asctime(time.localtime(timeinseconds))
File "/opt/s3tik/bin/duplicity", line 6, in isodate
return time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(timeinseconds))
TypeError: an integer is required (got type time.struct_time)

08:57:10.886 Task 'LIST' failed with exit code '30'.
--- Finished state FAILED 'code 30' at 08:57:10.886 - Runtime 00:00:00.351 ---

root@obertux:/opt/s3tik/bin# cat duplicity
#!/usr/bin/python3

import time

def isodate(timeinseconds):
return time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(timeinseconds))

time.asctime = isodate;

with open("/usr/bin/duplicity") as duplicity:
code = duplicity.read()
exec(code)


root@obertux:/opt/s3tik/bin# fpg -p asctime /usr/lib/python3/dist-packages/duplicity/dup_time.py
def timetopretty(timeinseconds):
u"""Return pretty version of time"""
return time.asctime(time.localtime(timeinseconds))
# return time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(timeinseconds))


Mit der letzten auskommentierten Zeile hatte es zuvor funktioniert.
Ich verstehe nicht, warum es nun zu obiger Fehlermeldung kommt (line 169
ist die drueber).
Was hab ich uebersehen?


>>> Was mich wieder zu der Frage zurückführt, wie Du da ein Wrapper-Script
>>> installieren willst.
>>
>> $HOME/bin, /var/tmp/bin, etc
>
> D.h. du willst das nur für dich, nicht für die anderen User des Systems?
> (Dass Du oben /opt erwähnst, widerspricht dem etwas)

Ich teste es erst mal lokal auf meinem eigenem System, da kann ich /opt
beschreiben.

Ulli Horlacher

unread,
Dec 5, 2022, 3:24:39 AM12/5/22
to
Habs nun geaendert zu:

root@obertux:/opt/s3tik/bin# cat duplicity
#!/usr/bin/python3

from duplicity import dup_time

def isodate(timeinseconds):
return time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(timeinseconds))

dup_time.timetopretty = isodate;

with open("/usr/bin/duplicity") as duplicity:
code = duplicity.read()
exec(code)


Ich definiere also nicht time.asctime() um, sondern dup_time.timetopretty()
Ist eh besser.
Und DAMIT funktioniert es:

root@obertux:/opt/s3tik/bin# duply root list | tail
2021-01-20 17:55:59 server/tacitus
2021-01-20 17:55:59 server/unifex
2021-01-20 17:56:00 server/zentux
2021-01-20 17:56:00 server/zoo
2022-12-03 06:57:02 tmp
2022-12-03 09:43:51 tmp/.zz
2015-04-28 15:08:50 vcli
2013-09-11 17:02:36 vminfo_example
2013-06-24 13:33:40 vmti
--- Finished state OK at 09:17:08.178 - Runtime 00:00:01.087 ---


==> Ich bekomme jetzt ISO Datum!

Und ich weiss nun, wie man Python-Programmen geaenderte Funktionen
unterschieben kann, ohne den Original Source Code aendern zu muessen.
Den Trick kann ich spaeter bestimmt noch oefters gebrauchen!
Sehr gut!

Peter Heitzer

unread,
Dec 5, 2022, 3:59:04 AM12/5/22
to
Ulli Horlacher <fram...@rus.uni-stuttgart.de> wrote:
>Mike Müller <mmue...@python-academy.de> wrote:

>>> ABER: duplicity ist ein Ubuntu-Paket und beim naechstes (automatischen)
>>> Update wird mein modifiziertes dup_time.py ersetzt.
>>> Irgendwelche Aenderungen des Original-Codes verbieten sich also.
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>>
>>> Meine Idee nun:
>>>
>>> Ich schreibe einen wrapper fuer duplicity, der time.asctime() durch meine
>>> obige Funktion ersetzt. So wuerde ich das zumindest bei C oder Perl machen.
>>>
>>> (Wie) geht das bei Python?
>>
>> import duplicity.dup_time
>>
>> def timetopretty(timeinseconds):
>> """Return pretty version of time"""
>> return time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(timeinseconds))
>>
>> duplicity.dup_time.timetopretty = timetopretty
>>
>> ganz zu Beginn des Programms sollte funktionieren.
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

>Funktioniert so nicht!

>Ich kann/will/darf das Original-Programm nicht veraendern!
PYTHONPATH auf ein Verzeichnis setzen, das eine modifizierte Version des
Moduls time enthält?


--
Dipl.-Inform(FH) Peter Heitzer, peter....@rz.uni-regensburg.de
Reply all
Reply to author
Forward
0 new messages