[!!! Erledig t!!!] try catch in FHEM Modulen

Begonnen von CoolTux, 02 Februar 2022, 13:24:26

Vorheriges Thema - Nächstes Thema

CoolTux

Hallo,

Folgenden Code verwende ich seit längerem in meinen eigenen Perlskripten und er scheint bisher ohne weiteres zu laufen.


use Carp;
use autodie qw /:io/;

try {

          .....

    }
    catch {
        if ( $_->isa('autodie::exception') && $_->matches(':io') ) {
           ........
        }
        else {
            croak $_;
        }
};


Nun habe ich versucht zum ersten mal diesen Code in einem FHEM Modul an zu wenden.

Im try {} wollte ich ein decode_json() ausführen. Dies hatte zur Folge das der else Zweig im catch ausgeführt wurde. Ich habe, nach dem das mit dem croak natürlich etwas "dumm" war, ein Log3 eingefügt und mir $_ ausgeben lassen. Hier wurden mir immer nur irgendwelche Raumnamen ausgegeben.
Hat jemand eine Idee wieso try catch generell nicht geht, weil der decode_json Befehl in try geht auf jeden Fall ohne Fehler.


Grüße
Marko
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

herrmannj

try/catch kommt doch nicht aus carp. Das kommt doch aus diversen cpan modulen... ?

Ich kann dir nicht sagen woran das hängt, aber klassisch eval { } ist keine Alternative? Gut abgehangen, gut dokumentiert, selbst die Bugs (in alten perl) sind gut dokumentiert. Im Unterschied zu einem string eval ist die Blockform auch performance mäßig ohne Einfluß.

eval {
...
1;
};
if ($@) {
...
}



Beta-User

In meinen aktuellen Überarbeitungen findet sich das in etwas anderer Form (hier aus msgDialog, indirekt in DefineFn()):
  my $content2 = msgDialog_evalSpecials($hash, $content);
  if ( !eval{ $content2 = JSON->new->decode($content2); 1;} ){ #decode_json will cause problems with utf8
    Log3($hash, 2, "msgDialog ($name) - DEF or configFile is not a valid JSON: $@");
    return("Usage: define <name> msgDialog {JSON}\n\n$@");
  }
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

CoolTux

Zitat von: herrmannj am 02 Februar 2022, 13:37:24
try/catch kommt doch nicht aus carp. Das kommt doch aus diversen cpan modulen... ?

Ich kann dir nicht sagen woran das hängt, aber klassisch eval { } ist keine Alternative? Gut abgehangen, gut dokumentiert, selbst die Bugs (in alten perl) sind gut dokumentiert. Im Unterschied zu einem string eval ist die Blockform auch performance mäßig ohne Einfluß.

eval {
...
1;
};
if ($@) {
...
}


Jepp kommt aus Carp. Deswegen lade ich ja Carp auch  :)



Zitat von: Beta-User am 02 Februar 2022, 13:52:26
In meinen aktuellen Überarbeitungen findet sich das in etwas anderer Form (hier aus msgDialog, indirekt in DefineFn()):
  my $content2 = msgDialog_evalSpecials($hash, $content);
  if ( !eval{ $content2 = JSON->new->decode($content2); 1;} ){ #decode_json will cause problems with utf8
    Log3($hash, 2, "msgDialog ($name) - DEF or configFile is not a valid JSON: $@");
    return("Usage: define <name> msgDialog {JSON}\n\n$@");
  }



Danke Dir das sieht so ähnlich aus wie das was ich aktuell mache. Etwas schöner muss ich gestehen. Werde ich mir wohl aneignen  ;D



Grüße
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

Beta-User

#4
Zitat von: CoolTux am 02 Februar 2022, 13:56:52
Danke Dir das sieht so ähnlich aus wie das was ich aktuell mache. Etwas schöner muss ich gestehen. Werde ich mir wohl aneignen  ;D
:) Hat eine Weile gebraucht, bis es so (mehr oder weniger überall) ausgesehen hat.

Wen es interessiert, warum das so zusammengezogen ist (Thx to Otto123 für den direkten Link): https://metacpan.org/pod/Perl::Critic::Policy::ErrorHandling::RequireCheckingReturnValueOfEval
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

CoolTux

Die Frage hat sich erübrigt. Die einfache Antwort ist "Ich bin ein Honk".

Beta-User hat mich durch seinen Link drauf gebracht was ich falsch gemacht habe.   ;D

Danke Euch
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

Beta-User

Zitat von: CoolTux am 02 Februar 2022, 14:12:25
Die Frage hat sich erübrigt. Die einfache Antwort ist
Nö. Das Thema findet sich (leider) überall quer durch den ganzen Code, und du bist der, der es hier aufgegriffen hat :) .

Wobei "Das Thema" erweitert ist: eval ohne Block-Form, überhaupt direktes eval (und nicht "AnalyzePerlCommand()") und eben das "if" außerhalb der Klammer... Viel Spaß beim Suchen (ich mache da mal bei Gelegenheit bei meinem jüngsten Neuzugang archetype das nächste "Massaker" (u.a.) in diese Richtung. Für msgDialog bin ich (hoffentlich) schon "verlustfrei" durch :) .)
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

CoolTux

Ich bleibe bei try / catch und habe es nun zum laufen gebracht.   ;D

Einfache Antwort. try / catch ist nicht in Carp sondern in Try::Tiny und das hatte ich nicht geladen gehabt. Ich muss mir mehr Notizen machen.
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

Beta-User

...nun denn, auch ein Lösung :) .

(Notiz an mich selbst: bei Gelegenheit mal schauen, ob das in corelist ist).
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

herrmannj

#9
und ich bleib dabei das try/catch nicht aus carp kommt :D -> https://perldoc.perl.org/Carp

?-> use Try::Tiny;

Aber wenns läuft ist schön. Den link mit dem eval Verhalten meinte ich mit "bekannte bugs"

edit. hab die antwort gesehen, check! Das geht mit core eval aber genauso ... man muss halt kurz aufpassen

herrmannj

Zitat von: Beta-User am 02 Februar 2022, 14:20:40
Nö. Das Thema findet sich (leider) überall quer durch den ganzen Code, und du bist der, der es hier aufgegriffen hat :) .

Wobei "Das Thema" erweitert ist: eval ohne Block-Form, überhaupt direktes eval (und nicht "AnalyzePerlCommand()") und eben das "if" außerhalb der Klammer... Viel Spaß beim Suchen (ich mache da mal bei Gelegenheit bei meinem jüngsten Neuzugang archetype das nächste "Massaker" (u.a.) in diese Richtung. Für msgDialog bin ich (hoffentlich) schon "verlustfrei" durch :) .)

Bin mir nicht sicher ob ich das verstehe. Eval mit string ist oft bequem, performance technisch aber eher suboptimal. Falls das string eval performance kritische stellen betrifft (event loop zb) kann man einen trick machen:

$fn = eval q(sub {return eval ...
dann $fn->('foo');

CoolTux

Zitat von: herrmannj am 02 Februar 2022, 14:37:55
und ich bleib dabei das try/catch nicht aus carp kommt :D -> https://perldoc.perl.org/Carp

?-> use Try::Tiny;

Aber wenns läuft ist schön. Dan link mit dem eval Verhalten meinte ich mit "bekannte bugs"

edit. hab dien antwort gesehen, check! Das geht mit core eval aber genauso ... man muss halt kurz aufpassen

Mein Fehler, ich habe das NICHT in Deinem Text nicht gesehen. Sonst wäre ich in der Tat früher drauf gekommen. Danke Jörg. Bisschen blind heute auf einem Auge  :D
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

CoolTux

Kurze Erklärung zu meinem Verhalten.

Ich nutzte try/catch weil es moderner ist und auch in anderen Sprachen so angewendet wird. Aktuell entwickel ich noch in Dart und damit ich da nicht zu sehr durcheinander komme nehme ich an modernen Mitteln für Perl was ich so finde.


Grüße
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

Beta-User

Zitat von: CoolTux am 02 Februar 2022, 14:46:38
Kurze Erklärung ...
Danke für den Hintergund. (muss trotzdem mal schauen, ob das core ist, sieht "nett" aus, und meine Module sind (demnächst hoffentlich wieder) alle eingepackt, so dass ich das stressfrei einbauen könnte).

Zitat von: herrmannj am 02 Februar 2022, 14:43:05
Bin mir nicht sicher ob ich das verstehe. Eval mit string ist oft bequem, performance technisch aber eher suboptimal. Falls das string eval performance kritische stellen betrifft (event loop zb) kann man einen trick machen:

$fn = eval q(sub {return eval ...
dann $fn->('foo');
Na ja, dann mal etwas mehr zum Hintergrund:
- Statistisch gesehen bin ich jetzt gefühlt bei der Überarbeitung der mir zugelaufenen Module (und ein paar weiteren, bei denen ich Teile vorgeschlagen habe) an ca. 40-70 "eval" in der String-Form begegnet. Effektiv konnte ich alle _bis auf eines_ durch entweder die Blockform (geschätzt ~80%) oder AnalyzePerlCommand() (der Rest) ersetzen.
- Meistens war es keine große Sache, man muss eigentlich nur den Unterschied kennen und checken, ob Block-eval nicht auch das gewünschte Ergebnis liefert => diese Fälle sind eigentlich keine große Sache und man fragt sich halt, warum da überhaupt mal ein String-eval verteilt wurde (verschenkte Performance; gerne anzutreffen ohne Analyse von $@).

- Der eine Fall der verbliebenen String-Form befindet sich nicht in einem meiner Module und ist in der Tat leider innerhalb einer NotifyFn, und wird dabei auch noch rekursiv aufgerufen (wobei ich davon ausgehe, dass ein User schon ziemlich kreativ sein muss, um da wirklich viel Last zu erzeugen). Das Problem dort ist, dass man eine ganze Latte von (sich bei jeder Rekursion ggf. ändernden!) Variablen innerhalb des eval kennen muss, so dass ich Zweifel habe, ob die "q"-Variante da funktionieren würde. Leider müßte ich mich auch erst mal wieder eindenken, um das überhaupt testen zu können... (Die Stelle nenne ich gerne auf Anfrage per pm).

- In den verbliebenen Fällen ging es in der Regel darum, User-Code (aus Attributen stammend) zu analysieren, und das geht mAn. "richtig" per AnalyzePerlCommand() (ggf. mit vorangegangenem EvalSpecials()). Da hat man dann zwar auch (indirekt) die Stringform, was aber ok ist, denn in der Regel ist das nicht ein "Dauerläufer", und man muss halt auch erst mal den finalen "Text" ermitteln, bevor es richtig losgehen kann... Die "verschenkte Performance" ist dabei halt hinzunehmen.
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files