Wie kann ich in Jupyter Notebook ein Modul in einer Zelle darstellen und ein ...

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Brando
User
Beiträge: 171
Registriert: Donnerstag 28. Januar 2016, 15:36

In Jupyter Notebook kann man in Zellen Python Code darstellen. Bislang bin ich so vorgegangen, dass ich in dem passenden Ordner für den Programmaufruf ein Pythonskript schreibe, welches ein Modul nutzt, welches am gleichen Ort gespeichert ist. Der Aufruf des Programmes erfolgt mittels exec_render(modulname), wobei exec_render die initiale Methode des Programmes ist, und modulname der Name des Moduls, welches das Programm nutzt. Jetzt möchte ich so vorgehen: In einer Zelle in Jupyter Notebook wird der Code des Moduls gesetzt. In der gleichen Zelle auch exec_render(), nur dass der Zelleninhalt bis auf die Zeile des Aufrufes exec_render als Modul genutzt wird.
------------------------------------------Jupyter Notebook Zelle
Modulcode
exec_render-Aufruf
_______________________________Ende Jupyter Notebook Zelle

exec_render nutzt den Modulcode

Wie geht das?
Sirius3
User
Beiträge: 18265
Registriert: Sonntag 21. Oktober 2012, 17:20

@Brando: eigentlich solltest Du gar kein "exec_render" benutzen, sondern einfach nur Funktionen schreiben (entweder in einem eigenen Modul oder direkt im Notebook) (möglichst ohne Nebeneffekte, kein global, keine Widgets in Berechungsfunktionen, etc) und diese einfach aufrufen.
Brando
User
Beiträge: 171
Registriert: Donnerstag 28. Januar 2016, 15:36

Mein Programm besteht aus Funktionen. Aber das Problem bleibt: Ich rufe die Funktion exec_render auf, diese ist im Dateisystem von Jupyter Notebook am richtigen Ort hinterlegt. Dann soll diese Funktion aber auf das Modul zugreifen, welches ich in eine Zelle schreibe, und nicht im Dateisystem hinterlegt ist. Das ganze soll von der entsprechenden Zelle im Jupyter Notebook aus gestartet werden.
Sirius3
User
Beiträge: 18265
Registriert: Sonntag 21. Oktober 2012, 17:20

@Brando: und was ist jetzt Dein Problem? Es ist doch egal, ob Deine Funktion importiert wird oder im selben Dokument definiert wird. Der Aufruf unterscheidet sich nicht.
Brando
User
Beiträge: 171
Registriert: Donnerstag 28. Januar 2016, 15:36

Bisher habe ich das Modul importiert. Dann hat exec_render einen Parameter, der auf das Modul verweist. Jetzt soll das Modul in eine Jupyter Notebook Zelle geschrieben werden und exec_render aufgerufen werden. D.h. das Modul und der Aufruf exec_render stehen in derselben Zeile. Wie teile ich dem Programm von exec_render mit, das er das Modul nutzen soll, welches in der Jupyter Notebook Zelle steht und wie wird das Problem behoben, dass das Modul und der Aufruf exec_render in derselben Zelle steht?
Brando
User
Beiträge: 171
Registriert: Donnerstag 28. Januar 2016, 15:36

So sieht meine Lösung bisher aus, sie funktioniert aber nicht. Globale Variablen werde ich noch beseitigen.

Code: Alles auswählen

from sympy.matrices import *
from builtins import str
from ipywidgets import widgets
from IPython.display import display, HTML, Math, Latex, clear_output
from random import randint
import sys
from sympy.matrices import *
from sympy.printing import *
from IPython.display import display, HTML, Math, Latex, clear_output
from ipywidgets import widgets
from random import randint
from sympy import *
from builtins import str
from copy import deepcopy
import numpy as np
import importlib
import matrix_mult_module as mmm
import sys
import sympy as sp
x=[]
tb_container=[]
def init_vector(matrix,m_2):
  global x
  x=[]
  a_matrix=zeros(matrix.shape[0], matrix.shape[1])
  b_matrix=zeros(matrix.shape[0], matrix.shape[1])
  for i in range(matrix.shape[0]):
    for j in range(matrix.shape[1]):
      a_matrix[i,j]=randint(-10,10)
      b_matrix[i,j]=randint(-10,10)
  x.append(a_matrix)
  x.append(b_matrix)
  a=[]
  for i in range(m_2):
             b=latex(x[i])
             b=b.replace("left[", "left(")
             b=b.replace("right]", "right)")
             a.append(b)
        
  str1="$\langle" 
  for i in range(m_2):
               if i==m_2-1:
                   str1=str1+a[i]
               else:
                   str1=str1+a[i]+", " 
  str1 += "\\rangle$"
  return str1

def init_containers(efeld):
  global tb_container
  tb_container = []
  c=[] 
  
  for j in range(efeld.shape[1]):
       for i in range(efeld.shape[0]):
               c.append(widgets.Text(Description="Thema", width=140))
       tb_container.append(widgets.HBox(children = [u for u in c]))
       c=[]
       
       
  
                
  return cb_container


def evaluate(Ergebnis): 
  global cb_container
  gefunden=True
  fehlerbericht=""
  Lösung=zeros(Ergebnis.shape[0], Ergebnis.shape[1])
  
  for i in range(Ergebnis.shape[0]):
    for j in range(Ergebnis.shape[1]):
      Lösung[i,j]=cb_container[i].children[j].value
      
  for i in range(Lösung.shape[0]):
    for j in range(Lösung.shape[1]):
      if str(Ergebnis[i,j]).strip() != str(Lösung[i,j]).strip():
        gefunden=False
        fehlerbericht+=" Fehler in Zelle "+ str(i)+" " +str(j) + " wahrer Wert ist " + str(Ergebnis[i,j]) + "\n"
    
  if gefunden==True:
    fehlerbericht=" Richtige Lösung "
  return gefunden, fehlerbericht


def rechne():
   z=x[0]*x[1]
  
   return evaluate(z)

exec_render(Matrix([[0,0],[0,0]]),"Matrixmultiplikation:", Matrix([[0,0],[0,0]]),2)
BlackJack

Brando hat geschrieben:Globale Variablen werde ich noch beseitigen.
Nein, das wirst Du nach den bisherigen Erfahrungen nicht tun. Genau so wenig wie Du irgendwelche anderen Hinweise bezüglich Konventionen zu sauberer, lesbarer, wartbarer Programmierung umsetzen wirst.

Was soll `exec_render()` in diesem Beispiel denn überhaupt bewirken? Was soll daraufhin ausgeführt werden und wohin werden die Argumente von dem Aufruf übergeben?

Räum doch bitte mal die Importe auf, entferne dabei die Sternchen-Importe, beseitige ``global``, rücke nach Konvention ein, und lern Python! So unsinnige Sachen wie ```` kann ich echt langsam nicht mehr sehen. :?
Brando
User
Beiträge: 171
Registriert: Donnerstag 28. Januar 2016, 15:36

exec_render ist mein Interface zur Darstellung der Eingabevektoren und zur Darstellung der Lösung. Die Eingabevektoren der Matrixmultiplikation werden aber in dem Modul erzeugt, welches ich oberhalb von exec_render eingefügt habe, ebenso das Ergebnis. exec_render ist also ein Programmfunktion eines Programmes, welches das in der Zelle angegebene Modul nutzt.
BlackJack

@Brando: Das ist komplett wirr! Wenn das da ein ”Modul” sein soll, dessen Quelltext in der Zelle steht, dann ist der Aufruf in der letzten Zeile *Teil* dieses ”Moduls”. Und Du willst dem Aufruf irgendwie das Modul mitgeben in dem er selber am Ende ausgeführt wird? Da beisst sich doch irgendwas in den Schwanz…

Das Problem fängt aber wohl da an, das einzelne Zelleninhalte keine Module sind. Warum muss das dort in einer Zelle stehen? Warum kannst Du nicht endlich mal den ganzen ``global``-Mist entfernen und dabei lernen wie man Funktionen und gegebenenfalls Klassen richtig verwendet? Denn dann würdest Du ziemlich sicher nicht *noch gruseligere* Magie als ``global`` ausprobieren, sondern der Funktion da einfach alles was sie braucht als Argumente übergeben. Die normale Lösung halt, die jeder Programmierer versteht, und bei der Du auch nach einem Jahr noch weisst was da wie zusammenhängt und funktioniert. Oder zumindest kannst Du Dich nach einem Jahr da leicht wieder einlesen ohne zu verzweifeln.
Brando
User
Beiträge: 171
Registriert: Donnerstag 28. Januar 2016, 15:36

soll ich dann exec_render aufrufen mit dem Quelltext des Programmes quelltext als Übergabeparameter von exec_render(quelltext)? Aber wie verarbeitet dann ipython diesen Quelltext als Modul, welches in dem Programm von exec_render benutzt wird?
BlackJack

@Brando: Nein, Du sollst das ganz anders lösen. Ganz normal halt. Ohne irgendwelche Magie mit implizitem übergeben von Modulen oder gar dem Quelltext von einem Modul.
Brando
User
Beiträge: 171
Registriert: Donnerstag 28. Januar 2016, 15:36

Ganz normal würde bedeuten, dass ich im Dateisystem ein Modul hinterlege, welches dann im Programm von exec_render eingebunden wird und ausgewertet wird. Das Problem ist nur, dass ich nach Aufgabenstgellung das Dateisystem nicht anrühren soll. Ich muss also irgendwie in eine Zelle einen Code als Modul schreiben, welches dann vom Interface mit der Initialmethode exec_render genutzt wird.
Sirius3
User
Beiträge: 18265
Registriert: Sonntag 21. Oktober 2012, 17:20

@Brando: was macht denn nun exec_render? Warum bekommt diese Funktion nicht alles, was sie braucht per Argumente? Solche blödsinnigen Abhängigkeiten kommen doch nur daher, dass Du alles per globaler Variablen machst und Deine def-Programm-Abschnitte (Funktionen darf man dazu nicht sagen) undurchsichtige Abhängigkeiten haben.
Brando
User
Beiträge: 171
Registriert: Donnerstag 28. Januar 2016, 15:36

exec_render ist die initiale Funktion eines Programmes la_scalar_8.py. Dieses Programm ist im für Jupyter Notebook relevanten Ordner abgelegt. Das Programm wird also mit exec_render gestartet, und nutzt ein Modul. Wie gesagt: Wenn ich das Modul am gleichen Ort wie la_scalar_8 speichere und dann exec_render(modulname) aufrufe funktioniert alles. Aber eben das darf ich nicht. Mein Modul soll in eine Zelle geschrieben werden, und ausgehend von dieser Zelle soll la_scalar_8 mittels exec_render dieses Modul nutzen. Im Grunde wäre das Problem gelöst, wenn ich lösen könnte wie die Funktionen eines Moduls in einer Zelle von einem externen Programm aus genutzt werden können.
BlackJack

@Brando: Was ist eine „initiale Funktion“? Was macht diese Funktion? Wenn die ein Modul importiert, dann solltest Du ihr halt ein Modul zum importieren zur Verfügung stellen, und zwar so und dort wie die Funktion das erwartet. Wenn Du das nicht darfst, kannst, oder willst, dann hast Du halt Pech gehabt, oder musst zu gruseligem Voodoo greifen und im Import-Mechanismus von Python herum hacken. Dazu müsste man aber Python können und nicht schon an einfachen Funktionen scheitern. Und wenn man genug Python-Kenntnisse hat, um so etwas umzusetzen, dann macht man das nicht, weil man dann Python gut genug beherrscht um solche komischen Verrenkungen gar nicht erst machen zu müssen.
Brando
User
Beiträge: 171
Registriert: Donnerstag 28. Januar 2016, 15:36

In Jupyter Notebook haben die aufgerufenen Programme keine main Methode. Sie werden von einer initialen Methode heraus gestartet. Das meine ich mit initial. Das Interface, welches so angesprochen wird greift dann theoretisch auf die Modulinhalte zu, die in einer jupyter cell niedergelegt werden. Der Aufruf dieser Methoden vom Interface aus ist aber nicht zu bewerkstelligen, weil der Zellinhalt nicht als relevant für das Interface erkannt wird.
Brando
User
Beiträge: 171
Registriert: Donnerstag 28. Januar 2016, 15:36

Selbst der Code funktioniert nicht:

Code: Alles auswählen

from sympy.matrices import *
from builtins import str
from ipywidgets import widgets
from IPython.display import display, HTML, Math, Latex, clear_output
from random import randint
import sys
from sympy.matrices import *
from sympy.printing import *
from IPython.display import display, HTML, Math, Latex, clear_output
from ipywidgets import widgets
from random import randint
from sympy import *
from builtins import str
from copy import deepcopy
import numpy as np
import importlib
import matrix_mult_module as mmm
import sys
import sympy as sp




sys.path.insert(0,"/home/Brando/.ipython/profile_default/startup")
x=[]
tb_container=[]
def init_vector(matrix,m_2):
  global x
  x=[]
  a_matrix=zeros(matrix.shape[0], matrix.shape[1])
  b_matrix=zeros(matrix.shape[0], matrix.shape[1])
  for i in range(matrix.shape[0]):
    for j in range(matrix.shape[1]):
      a_matrix[i,j]=randint(-10,10)
      b_matrix[i,j]=randint(-10,10)
  x.append(a_matrix)
  x.append(b_matrix)
  a=[]
  for i in range(m_2):
             b=latex(x[i])
             b=b.replace("left[", "left(")
             b=b.replace("right]", "right)")
             a.append(b)
        
  str1="$\langle" 
  for i in range(m_2):
               if i==m_2-1:
                   str1=str1+a[i]
               else:
                   str1=str1+a[i]+", " 
  str1 += "\\rangle$"
  return str1

def init_containers(efeld):
  global tb_container
  tb_container = []
  c=[] 
  
  for j in range(efeld.shape[1]):
       for i in range(efeld.shape[0]):
               c.append(widgets.Text(Description="Thema", width=140))
       tb_container.append(widgets.HBox(children = [u for u in c]))
       c=[]
       
       
  
                
  return tb_container


def evaluate(Ergebnis): 
  global tb_container
  gefunden=True
  fehlerbericht=""
  Lösung=zeros(Ergebnis.shape[0], Ergebnis.shape[1])
  
  for i in range(Ergebnis.shape[0]):
    for j in range(Ergebnis.shape[1]):
      Lösung[i,j]=tb_container[i].children[j].value
      
  for i in range(Lösung.shape[0]):
    for j in range(Lösung.shape[1]):
      if str(Ergebnis[i,j]).strip() != str(Lösung[i,j]).strip():
        gefunden=False
        fehlerbericht+=" Fehler in Zelle "+ str(i)+" " +str(j) + " wahrer Wert ist " + str(Ergebnis[i,j]) + "\n"
    
  if gefunden==True:
    fehlerbericht=" Richtige Lösung "
  return gefunden, fehlerbericht


def rechne():
   z=x[0]*x[1]
  
   return evaluate(z)

def initialisiere(): 
    i_progr=importlib.import_module("la_scalar_8") 
    i_progr.exec_render(Matrix([[0,0],[0,0]]),"Matrixmultiplikation:", Matrix([[0,0],[0,0]]),2)
    
initialisiere()
Sirius3
User
Beiträge: 18265
Registriert: Sonntag 21. Oktober 2012, 17:20

@Brando: wenn la_scalar_8 ein Modul ist, das Du einfach importieren kannst, dann mach das doch mit "import" und mach nicht solche Verrenkungen.
Dass inzwischen alle Importe doppelt sind, macht die Sache nicht besser. Ein "funktioniert nicht" ist bei der Fehlersuche nicht sehr hilfreich. Bisher ist glaube ich noch niemandem hier klar, was eigentlich Dein Problem ist.
Brando
User
Beiträge: 171
Registriert: Donnerstag 28. Januar 2016, 15:36

Ein einfaches import löst das Problem auch nicht. Es wird nicht erkannt, was ich an Methoden in die Zelle geschrieben habe. Die Fehlermeldung lautet:
NameError: name 'init_vector' is not defined.

Also genau die Methode, die ich in der Zelle verwende wird nicht erkannt.
BlackJack

@Brando: Also mir ist immer noch nicht ganz klar wie das funktionieren soll. Diese Meldung kommt vom importieren des Moduls? Dann fehlt dem diese Funktion, oder aber es läuft Code mit Nebeneffekten beim importieren, was nicht sein sollte, denn dann kann man das Modul nicht sinnvoll als Modul verwenden.

@Sirius3: Also das eigentliche Problem ist mir schon klar, und das sitzt IMHO eindeutig vor dem Rechner. :twisted:
Antworten