C++ und Python

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
Centurius
User
Beiträge: 22
Registriert: Dienstag 14. März 2017, 14:09

Guten Tag,

ich habe ein Programm geschrieben, das in der Lage ist Python Scripte reinzuladen. Zur Zeit lade ich über die Funktion PyImport_Import die Scripts rein und das klappt alles soweit.

Nur was ist der Unterschied zu PyImport_ImportModule?

Ist es möglich das ein Script, das reingeladen wurde, in ein anderes Script zu importieren? Also sprich es werden Test1.py und Test2.py reingeladen. Nun möchte ich gerne in Test2.py import Test1 nutzen ohne das sie im selben Ordner sind oder ist es anders möglich an die Funktionen von Test1.py zukommen?

Gibt es außerdem eine Möglichkeit "import os" zu verbieten und es um "import MySQLdb" zu erlauben?
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@Centurius: der Unterschied steht in der Dokumentation. Bei PyImport_Import: This is a higher-level interface that calls the current “import hook function”, PyImport_ImportModule umgeht eventuelle Hooks und ruft das Ursprüngliche __import __ direkt auf.

Ja, man kann Test1 in Test2 importieren: Mit import.

Es macht keinen Sinn, irgendwo "import os" zu verbieten. Wenn Du bestimmte Systemfunktionen verbieten willst, mußt Du einige Ebenen tiefer ansetzen. Das sauber umzusetzen ist so gut wie unmöglich, wenn Du auch noch an einigen Stellen mehr erlauben willst als an anderen.
Centurius
User
Beiträge: 22
Registriert: Dienstag 14. März 2017, 14:09

Danke für deine Antwort! :)

Ich würde aus Sicherheitsaspekten gerne alle OS.* Funktionen verbieten wollen.

Ne das Importieren funktioniert bei mir nicht.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wir verstehen schon warum du das willst. Es ist ein immer wieder und immer wieder erfolglos diskutiertes Thema, dessen Antwort ist: geht nicht. Es gibt eine Zillion Moeglichkeiten, an die entsprechenden Funktionen zu kommen.
BlackJack

@Centurius: Das mit den `os`-Funktionen musst Du ausserhalb von Python lösen und dann aber auch bedenken was denn passieren soll wenn irgendein Modul solche Funktionen verwenden will. Also zum Beispiel ein Datenbankmodul. Es ist also letztendlich innerhalb von Python nicbt möglich. Darauf ist die Python-Laufzeitumgebung nicht ausgelegt. Es gab in der Standardbibliothek mal ein Modul für ”Sandkästen”, das ist aber rausgeflogen weil jahrelang immer wieder neue Möglichkeiten gefunden wurden da auszubrechen. Pack Deinen kompletten Prozess in eine chroot-Umgebung oder etwas vergleichbares.
Centurius
User
Beiträge: 22
Registriert: Dienstag 14. März 2017, 14:09

Gut, dann gebe ich mich damit zufrieden.

Nur ein Problem mit dem import besteht noch.
Kann das sein, das es daran liegt, das ich vor dem PyImport_Import mit PySys_SetPath das Verzeichnis ändere, das er deshalb das andere Script nicht findet?

Gibt es noch eine andere Möglichkeit bei PyImport_Import das Verzeichnis mit anzugeben?
BlackJack

@Centurius: Was heisst ”ändern”? Den sollte man natürlich nur erweitern. Wenn man da Pfade rauslöscht von denen schon importiert wurde, könnte das lustige Effekte haben wenn versucht wird daraus später noch mal oder noch mehr zu importieren.
Centurius
User
Beiträge: 22
Registriert: Dienstag 14. März 2017, 14:09

Gibt es eine Möglichkeit, das ich zum Beispiel die Funktion print überschreibe?
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@Centurius: ja?

Code: Alles auswählen

print = irgendwas_anderes
Centurius
User
Beiträge: 22
Registriert: Dienstag 14. März 2017, 14:09

Sirius3 hat geschrieben:@Centurius: ja?

Code: Alles auswählen

print = irgendwas_anderes
Auch so das bei jedem PyImport_Import diese Funktionen überschrieben werden? Also das ich es im C++ Code angebe
BlackJack

@Centurius: Wenn Du es im `__builtins__`- bzw. `builtins`-Modul überschreibst, dann gilt es überall.
Centurius
User
Beiträge: 22
Registriert: Dienstag 14. März 2017, 14:09

BlackJack hat geschrieben:@Centurius: Wenn Du es im `__builtins__`- bzw. `builtins`-Modul überschreibst, dann gilt es überall.
Ähm, ich weiß nicht so genau was ich jetzt machen soll^^

Also vielleicht erläutere ich mal meine Problemstellung genau. Ich habe eine Module für Python gebaut und das lass ich mit "PyImport_AppendInittab" reinladen.
Als nächstes werden mehrere Python Scripts (PyImport_Import) geladen, die mit "Import Module" das Module importieren und die Funktionen des Modules ausführen.

Nun möchte ich gerne das automatisch die print Funktion überschrieben wird mit einer C++ Funktion.
Könnte ich das in das Module mit einbauen?
BlackJack

@Centurius: Wenn Du `print()` generell durch ein eigenes austauschen möchtest, dann müsstest Du das `__builtin__`- (Python 2) oder `builtins`-Modul (Python 3) importieren und die dort vorhandene `print`-Funktion durch eine eigene Funktion (mit kompatibler Signatur) ersetzen. Also in Python (2):

Code: Alles auswählen

from __future__ import print_function
import __builtin__

def print(…):
    …

__builtin__.print = print
Centurius
User
Beiträge: 22
Registriert: Dienstag 14. März 2017, 14:09

Kann ich das auch in C++ programmieren?
BlackJack

@Centurius: Ja, natürlich kann man alles was in Python gemacht wird auch über die API von C oder C++ aus gemacht werden. Deine `print()`-Funktion musst Du dann in einem Modul haben, das und das `__builtin__`/`builtins`-Modul importieren und dann das `print`-Attribut vom einen Modul abfragen und beim anderen Modul setzen.
Centurius
User
Beiträge: 22
Registriert: Dienstag 14. März 2017, 14:09

Die print Funktion habe ich in C++

Nun versuche ich nur noch mit einem C++ Befehl das print zu ersetzen. Wie mache ich das?

Edit: Habe es nun mit PyRun_SimpleString und darin den Python Code geschrieben gelöst. Ist das clever?

Eine andere Frage habe ich auch noch. Kann man beim Compilieren eines C++ ein Pyton Script importieren, das beim Ausführen immer importiert wird und nicht veränderbar ist?
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@Centurius: Es gibt auch das C-Funktionsäquivalent zu "setattr", nichts anderes ist ja das Setzen eines Wertes in einem Modul. Was Du mit "nicht veränderbar" meinst, verstehe ich nicht.
Centurius
User
Beiträge: 22
Registriert: Dienstag 14. März 2017, 14:09

Wenn ich ein Python Script das im Ordner liegt einlesen lasse, dann ist das veränderbar.
Also ein Script das nicht zur Laufzeit von Python eingelesen wird, sondern beim Compilieren schon eingelesen wurde und somit fest im Programm steht.

Kann man den TraceBack in ein String umwandeln?
BlackJack

@Centurius: Fest im Programm stehen schützt nicht davor das sich da jemand mit einem Hexeditor drüber her macht. Mit relativ kleinen Änderungen könnte man da beliebig viel Python-Code ausführen, denn man muss ja nur etwas eigenes von dort importieren lassen, das dann ausserhalb der EXE abgelegt ist.

Ja, man kann Tracebacks in Zeichenketten umwandeln: `traceback`-Modul in der Standardbibliothek.
Centurius
User
Beiträge: 22
Registriert: Dienstag 14. März 2017, 14:09

Ich hab folgendes probiert:

Code: Alles auswählen

PyObject *type = NULL, *value = NULL, *traceback = NULL, *pyString = NULL;
PyErr_Fetch(&type, &value, &traceback);
PyErr_Clear();
std::string message;
if (traceback != NULL && PyTraceBack_Check(traceback)) {
  message = PyUnicode_AsUFT8(traceback);
}
Ich weiß nicht wie ich traceback in einen String oder Char* bekomme
Zuletzt geändert von Anonymous am Mittwoch 15. März 2017, 20:30, insgesamt 2-mal geändert.
Grund: Quelltext in Codebox-Tags gesetzt.
Antworten