WxPython in web with a cgi server - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: GUI (https://python-forum.io/forum-10.html) +--- Thread: WxPython in web with a cgi server (/thread-16431.html) Pages:
1
2
|
WxPython in web with a cgi server - jttolleson - Feb-28-2019 HELLO, My name is Jayson, I am new to this forum and thought it would unravel my issue: A web based GUI in a python script??? I always need to attach a display by the end and I cannot get through... HERE WE GO: I have a website on a gcloud ubuntu 18 virtual machine (g1). https://35.236.122.135 The site is slung from a webserver on port 443 for webrtc with cgi via https://35.236.122.135/webserver3.py In https://35.236.122.135/cgi-bin/ I run python scripts, also deeper In https://35.236.122.135/cgi-bin/lftr/music/ I have 4 scripts that are relevant 1: https://35.236.122.135/cgi-bin/lftr/music/AUDIO_TO_MIDI_PLAYER.py 2: https://35.236.122.135/cgi-bin/lftr/music/GETandUPLOAD_AUDIO.py 3: https://35.236.122.135/cgi-bin/lftr/music/CONVERT_AUDIO_TO_MIDI.py 4: https://35.236.122.135/cgi-bin/lftr/music/PLAY_MIDI.py They are not just up, they will run in position. Also. now. when I run it by going to https://35.236.122.135/cgi-bin/lftr/music/AUDIO_TO_MIDI_PLAYER.py ; or cd /var/www/cgi-bin/lftr/music then sudo python3 AUDIO_TO_MIDI_PLAYER.py I GET MY ERROR: NO DISPLAY for the website "Unable to access the X Display, is $DISPLAY set Properly?" would anyone be able to assist me in my quest to have this work?... RE: WxPython in web with a cgi server - Larz60+ - Feb-28-2019 First url is not secure. didn't attempt anymore. Post code here in code tags see: BBcode RE: WxPython in web with a cgi server - jttolleson - Feb-28-2019 Ok...will do...jayt. I have a self signed cert for my webserver to get https and run webrtc. Anyway...the files. On Linux in the structure outlined in the first post: webserver3.py import os, sys from http.server import HTTPServer, CGIHTTPRequestHandler import ssl webdir = '/var/www/' port = 443 os.chdir(webdir) srvaddr=('', port) srvobj = HTTPServer(srvaddr, CGIHTTPRequestHandler) srvobj.socket = ssl.wrap_socket (srvobj.socket, keyfile='/var/security/35.236.122.135.key', certfile='/var/security/35.236.122.135.crt', server_side=True) CGIHTTPRequestHandler.have_fork=False # Force the use of a subprocess srvobj.serve_forever()1:AUDIO_TO_MIDI_PLAYER.py #!usr/bin/env python3 import cgitb cgitb.enable import os import wx import os class MyForm(wx.Frame): def __init__(self): wx.Frame.__init__(self, None, wx.ID_ANY, "Launch Scripts") panel = wx.Panel(self, wx.ID_ANY) sizer = wx.BoxSizer(wx.VERTICAL) buttonA = wx.Button(panel, id=wx.ID_ANY, label="App A", name="GETandUPLOAD_AUDIO") buttonB = wx.Button(panel, id=wx.ID_ANY, label="App B", name="CONVERT_AUDIO_TO_MIDI") buttonC = wx.Button(panel, id=wx.ID_ANY, label="App C", name="PLAY_MIDI") buttons = [buttonA, buttonB, buttonC] for button in buttons: self.buildButtons(button, sizer) panel.SetSizer(sizer) def buildButtons(self, btn, sizer): btn.Bind(wx.EVT_BUTTON, self.onButton) sizer.Add(btn, 0, wx.ALL, 5) def onButton(self, event): button = event.GetEventObject() os.system('python {}.py'.format(button.GetName())) button_id = event.GetId() button_by_id = self.FindWindowById(button_id) print ("The button you pressed was labeled: " + button_by_id.GetLabel()) print ("The button's name is " + button_by_id.GetName()) # Run the program if __name__ == "__main__": app = wx.App(False) frame = MyForm() frame.Show() app.MainLoop() print ('''Content-Type: text/html''') print print ('''<html> <?php ?> <html> <head> <meta charset="UTF-8"> <title>MUSIC - audio to midi player</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <style>* { padding: 0; margin: 0; } a { color: #337ab7; } p { margin-top: 1rem; } a:hover { color:#23527c; } a:visited { color: #8d75a3; } body { margin: 1rem; padding: 1rem; font-family: sans-serif; max-width: 28rem; margin: 0 auto; position: relative; } #controls { display: flex; margin-top: 2rem; } button { flex-grow: 1; height: 2.5rem; min-width: 2rem; border: none; border-radius: 0.15rem; background: #ed341d; margin-left: 2px; box-shadow: inset 0 -0.15rem 0 rgba(0, 0, 0, 0.2); cursor: pointer; display: flex; justify-content: center; align-items: center; color:#ffffff; font-weight: bold; font-size: 1rem; } button:hover, button:focus { outline: none; background: #c72d1c; } button::-moz-focus-inner { border: 0; } button:active { box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.2); line-height: 3rem; } button:disabled { pointer-events: none; background: lightgray; } button:first-child { margin-left: 0; } audio { display: block; width: 100%; margin-top: 0.2rem; } li { list-style: none; margin-bottom: 1rem; } #formats { margin-top: 0.5rem; font-size: 80%; } </style>''')2: GETandUPLOAD_AUDIO.py #!usr/bin/env python3 import cgitb cgitb.enable print ('''Content-Type: text/html''') print print ('''<html> <html> <body> <h1>RECORD AUDIO .wav to convert to midi</h1> <div id="controls"> <button id="recordButton">Record</button> <button id="pauseButton" disabled>Pause</button> <button id="stopButton" disabled>Stop</button> </div> <div id="formats">Format: start recording to see sample rate</div> <h3>Recordings</h3> <ol id="recordingsList"></ol> <script src="https://cdn.rawgit.com/mattdiamond/Recorderjs/08e7abd9/dist/recorder.js"></script> <script>URL = window.URL || window.webkitURL; var gumStream; //stream from getUserMedia() var rec; //Recorder.js object var input; //MediaStreamAudioSourceNode we'll be recording // shim for AudioContext when it's not avb. var AudioContext = window.AudioContext || window.webkitAudioContext; var audioContext //audio context to help us record var recordButton = document.getElementById("recordButton"); var stopButton = document.getElementById("stopButton"); var pauseButton = document.getElementById("pauseButton"); //add events to those 2 buttons recordButton.addEventListener("click", startRecording); stopButton.addEventListener("click", stopRecording); pauseButton.addEventListener("click", pauseRecording); function startRecording() { console.log("recordButton clicked"); /* Simple constraints object, for more advanced audio features see https://addpipe.com/blog/audio-constraints-getusermedia/ */ var constraints = { audio: true, video:false } /* Disable the record button until we get a success or fail from getUserMedia() */ recordButton.disabled = true; stopButton.disabled = false; pauseButton.disabled = false /* We're using the standard promise based getUserMedia() https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia */ navigator.mediaDevices.getUserMedia(constraints).then(function(stream) { console.log("getUserMedia() success, stream created, initializing Recorder.js ..."); /* create an audio context after getUserMedia is called sampleRate might change after getUserMedia is called, like it does on macOS when recording through AirPods the sampleRate defaults to the one set in your OS for your playback device */ audioContext = new AudioContext(); //update the format document.getElementById("formats").innerHTML="Format: 1 channel pcm @ "+audioContext.sampleRate/1000+"kHz" /* assign to gumStream for later use */ gumStream = stream; /* use the stream */ input = audioContext.createMediaStreamSource(stream); /* Create the Recorder object and configure to record mono sound (1 channel) Recording 2 channels will double the file size */ rec = new Recorder(input,{numChannels:1}) //start the recording process rec.record() console.log("Recording started"); }).catch(function(err) { //enable the record button if getUserMedia() fails recordButton.disabled = false; stopButton.disabled = true; pauseButton.disabled = true }); } function pauseRecording(){ console.log("pauseButton clicked rec.recording=",rec.recording ); if (rec.recording){ //pause rec.stop(); pauseButton.innerHTML="Resume"; }else{ //resume rec.record() pauseButton.innerHTML="Pause"; } } function stopRecording() { console.log("stopButton clicked"); //disable the stop button, enable the record too allow for new recordings stopButton.disabled = true; recordButton.disabled = false; pauseButton.disabled = true; //reset button just in case the recording is stopped while paused pauseButton.innerHTML="Pause"; //tell the recorder to stop the recording rec.stop(); //stop microphone access gumStream.getAudioTracks()[0].stop(); //create the wav blob and pass it on to createDownloadLink rec.exportWAV(createDownloadLink); } function createDownloadLink(blob) { var url = URL.createObjectURL(blob); var au = document.createElement('audio'); var li = document.createElement('li'); var link = document.createElement('a'); //name of .wav file to use during upload and download (without extendion) var filename = 'Recording'; //add controls to the <audio> element au.controls = true; au.src = url; //save to disk link link.href = url; link.download = filename+".wav"; //download forces the browser to donwload the file using the filename link.innerHTML = "Save to disk"; //add the new audio element to li li.appendChild(au); //add the filename to the li li.appendChild(document.createTextNode(filename+".wav ")) //add the save to disk link to li li.appendChild(link); //upload link var upload = document.createElement('a'); upload.href="#"; upload.innerHTML = "Upload"; upload.addEventListener("click", function(event){ var xhr=new XMLHttpRequest(); xhr.onload=function(e) { if(this.readyState === 4) { console.log("Server returned: ",e.target.responseText); } }; var fd=new FormData(); fd.append("audio_data",blob, filename); xhr.open("POST","upload.php",true); xhr.send(fd); }) li.appendChild(document.createTextNode (" "))//add a space in between li.appendChild(upload)//add the upload link to li //add the li element to the ol recordingsList.appendChild(li); }</script> </body> </html>''') print ('''''') print ('''''') print ('''''') print ('''''') print ('''<html><h1>Directory Listing:</h1></html>''') print ('''<html><h1>/var/www/cgi-bin/lftr/</h1></html>''') print ('''<html><h1>[music][audio][midi]</h1></html>''') folder = os.listdir("/var/www/cgi-bin/lftr/music/") audiofolder = os.listdir("/var/www/cgi-bin/lftr/music/audio") midifolder = os.listdir("/var/www/cgi-bin/lftr/music/midi") print ('''''') print ('''''') print ('''''') print ('''''') print (folder) print (audiofolder) print (midifolder)3: CONVERT_AUDIO_TO_MIDI.py #!usr/bin/env python3 import cgitb cgitb.enable print ('''Content-Type: text/html''') print print ('''<html> </html>''') print ('''''') print ('''''') print ('''''') print ('''''') print ('''<html><h1>Directory Listing:</h1></html>''') print ('''<html><h1>/var/www/cgi-bin/lftr/</h1></html>''') print ('''<html><h1>[music][audio][midi]</h1></html>''') folder = os.listdir("/var/www/cgi-bin/lftr/music/") audiofolder = os.listdir("/var/www/cgi-bin/lftr/music/audio") midifolder = os.listdir("/var/www/cgi-bin/lftr/music/midi") print ('''''') print ('''''') print ('''''') print ('''''') print (folder) print (audiofolder) print (midifolder) print ('''''') print ('''''') print ('''''') print ('''''') print ('''''') print ('''''') print ('''''') print ('''''') # CREATED: 11/9/15 3:57 PM by Justin Salamon <[email protected]> import librosa import vamp import argparse import os import numpy as np from midiutil.MidiFile import MIDIFile from scipy.signal import medfilt import jams import __init__ ''' Extract the melody from an audio file and convert it to MIDI. The script extracts the melody from an audio file using the Melodia algorithm, and then segments the continuous pitch sequence into a series of quantized notes, and exports to MIDI using the provided BPM. If the --jams option is specified the script will also save the output as a JAMS file. Note that the JAMS file uses the original note onset/offset times estimated by the algorithm and ignores the provided BPM value. Note: Melodia can work pretty well and is the result of several years of research. The note segmentation/quantization code was hacked in about 30 minutes. Proceed at your own risk... :) usage: audio_to_midi_melodia.py [-h] [--smooth SMOOTH] [--minduration MINDURATION] [--jams] infile outfile bpm Examples: python audio_to_midi_melodia.py --smooth 0.25 --minduration 0.1 --jams ~/song.wav ~/song.mid 60 ''' def save_jams(jamsfile, notes, track_duration, orig_filename): # Construct a new JAMS object and annotation records jam = jams.JAMS() # Store the track duration jam.file_metadata.duration = track_duration jam.file_metadata.title = orig_filename midi_an = jams.Annotation(namespace='pitch_midi', duration=track_duration) midi_an.annotation_metadata = \ jams.AnnotationMetadata( data_source='audio_to_midi_melodia.py v%s' % __init__.__version__, annotation_tools='audio_to_midi_melodia.py (https://github.com/' 'justinsalamon/audio_to_midi_melodia)') # Add midi notes to the annotation record. for n in notes: midi_an.append(time=n[0], duration=n[1], value=n[2], confidence=0) # Store the new annotation in the jam jam.annotations.append(midi_an) # Save to disk jam.save(jamsfile) def save_midi(outfile, notes, tempo): track = 0 time = 0 midifile = MIDIFile(1) # Add track name and tempo. midifile.addTrackName(track, time, "MIDI TRACK") midifile.addTempo(track, time, tempo) channel = 0 volume = 100 for note in notes: onset = note[0] * (tempo/60.) duration = note[1] * (tempo/60.) # duration = 1 pitch = note[2] midifile.addNote(track, channel, pitch, onset, duration, volume) # And write it to disk. binfile = open(outfile, 'wb') midifile.writeFile(binfile) binfile.close() def midi_to_notes(midi, fs, hop, smooth, minduration): # smooth midi pitch sequence first if (smooth > 0): filter_duration = smooth # in seconds filter_size = int(filter_duration * fs / float(hop)) if filter_size % 2 == 0: filter_size += 1 midi_filt = medfilt(midi, filter_size) else: midi_filt = midi # print(len(midi),len(midi_filt)) notes = [] p_prev = None duration = 0 onset = 0 for n, p in enumerate(midi_filt): if p == p_prev: duration += 1 else: # treat 0 as silence if p_prev > 0: # add note duration_sec = duration * hop / float(fs) # only add notes that are long enough if duration_sec >= minduration: onset_sec = onset * hop / float(fs) notes.append((onset_sec, duration_sec, p_prev)) # start new note onset = n duration = 1 p_prev = p # add last note if p_prev > 0: # add note duration_sec = duration * hop / float(fs) onset_sec = onset * hop / float(fs) notes.append((onset_sec, duration_sec, p_prev)) return notes def hz2midi(hz): # convert from Hz to midi note hz_nonneg = hz.copy() idx = hz_nonneg <= 0 hz_nonneg[idx] = 1 midi = 69 + 12*np.log2(hz_nonneg/440.) midi[idx] = 0 # round midi = np.round(midi) return midi def audio_to_midi_melodia(infile, outfile, bpm, smooth=0.25, minduration=0.1, savejams=False): # define analysis parameters fs = 44100 hop = 128 # load audio using librosa print("Loading audio...") data, sr = librosa.load(infile, sr=fs, mono=True) # extract melody using melodia vamp plugin print("Extracting melody f0 with MELODIA...") melody = vamp.collect(data, sr, "mtg-melodia:melodia", parameters={"voicing": 0.2}) # hop = melody['vector'][0] pitch = melody['vector'][1] # impute missing 0's to compensate for starting timestamp pitch = np.insert(pitch, 0, [0]*8) # debug # np.asarray(pitch).dump('f0.npy') # print(len(pitch)) # convert f0 to midi notes print("Converting Hz to MIDI notes...") midi_pitch = hz2midi(pitch) # segment sequence into individual midi notes notes = midi_to_notes(midi_pitch, fs, hop, smooth, minduration) # save note sequence to a midi file print("Saving MIDI to disk...") save_midi(outfile, notes, bpm) if savejams: print("Saving JAMS to disk...") jamsfile = outfile.replace(".mid", ".jams") track_duration = len(data) / float(fs) save_jams(jamsfile, notes, track_duration, os.path.basename(infile)) print("Conversion complete.") if __name__ == "__main__": audio_to_midi_melodia(Recording.wav, Recording.mid, 87, smooth=.25, minduration=.2)4: PLAY_MIDI.py #!usr/bin/env python3 import cgitb cgitb.enable import mido msg = mido.Message('note_on", note=60) msg.type msg.note msg.bytes() msg.copy(channel=2) port = mido.open_output('Port Name') port.send(msg) with mido.open_input() as inport: for msg in inport: print(msg) mid = mido.MidiFile('Recording.mid') for msg in mid.play(): port.send(msg)I know I have some work to do but the concept is hurt too RE: WxPython in web with a cgi server - jttolleson - Feb-28-2019 While there are other errors the main issue still stands with script 1: AUDIO_TO_MIDI_PLAYER.py. When it runs it doesn't have a display..... RE: WxPython in web with a cgi server - Larz60+ - Feb-28-2019 I have set up an environment and will see If I can be of service, no promises, and it will take some time to familiarize myself with your code. I won't be able to run though because even though I have what is supposed to be a good install of wxpython on my Linux Mint environment, I haven't been able to successfully use it. I am quite familiar with the phoenix version and have used it extensively on MS windows, but not here. I don't expect I will respond again on this until some time tomorrow. Perhaps someone else in a better position to help will respond before then. RE: WxPython in web with a cgi server - jttolleson - Feb-28-2019 Yes...it was some hours of compiling on a g1 for wxPython Phoenix in ubuntu18 I used pip3 install mostly RE: WxPython in web with a cgi server - jttolleson - Mar-02-2019 I suppose I am looking for a Display Back-end. Similar to GTK's Broadwayd. https://developer.gnome.org/gtk3/stable/broadwayd.html Through my research i have found ipython and it may be relevent if i rewrite my script some. https://ipython.org/ipython-doc/3/interactive/reference.html#interactive-demos-with-ipython RE: WxPython in web with a cgi server - Larz60+ - Mar-02-2019 I stopped playing this after mucking around once again, trying to get wxpython to install properly. It installs, but is not usable. RE: WxPython in web with a cgi server - jttolleson - Mar-03-2019 Yes, Hello again ---Jayson: wxPython will work in with IPython in Python3. Especially, in deb or ubuntu and this will be my direction, however the same problem exists. My x-display in web. I will post again as this thread continues, with a simple script that will have the same issue. the x display. Ok, well here we go: IPython sudo nohup python3 /var/www/webserver3.py & import os, sys from http.server import HTTPServer, CGIHTTPRequestHandler import ssl webdir = '/var/www/' port = 443 os.chdir(webdir) srvaddr=('', port) srvobj = HTTPServer(srvaddr, CGIHTTPRequestHandler) srvobj.socket = ssl.wrap_socket (srvobj.socket, keyfile='/var/security/35.236.122.135.key', certfile='/var/security/35.236.122.135.crt', server_side=True) CGIHTTPRequestHandler.have_fork=False # Force the use of a subprocess srvobj.serve_forever()sudo python3 /var/www/cgi-bin/lftr/wxgui.py #!/usr/bin/env python3 import cgitb cgitb.enable """ A Simple wx example to test IPython's event loop integration. To run this do: In [5]: %gui wx # or start IPython with '--gui wx' In [6]: %run gui-wx.py Ref: Modified from wxPython source code wxPython/samples/simple/simple.py """ import wx class MyFrame(wx.Frame): """ This is MyFrame. It just shows a few controls on a wxPanel, and has a simple menu. """ def __init__(self, parent, title): wx.Frame.__init__(self, parent, -1, title, pos=(150, 150), size=(350, 200)) # Create the menubar menuBar = wx.MenuBar() # and a menu menu = wx.Menu() # add an item to the menu, using \tKeyName automatically # creates an accelerator, the third param is some help text # that will show up in the statusbar menu.Append(wx.ID_EXIT, "E&xit\tAlt-X", "Exit this simple sample") # bind the menu event to an event handler self.Bind(wx.EVT_MENU, self.OnTimeToClose, id=wx.ID_EXIT) # and put the menu on the menubar menuBar.Append(menu, "&File") self.SetMenuBar(menuBar) self.CreateStatusBar() # Now create the Panel to put the other controls on. panel = wx.Panel(self) # and a few controls text = wx.StaticText(panel, -1, "Hello World!") text.SetFont(wx.Font(14, wx.SWISS, wx.NORMAL, wx.BOLD)) text.SetSize(text.GetBestSize()) btn = wx.Button(panel, -1, "Close") funbtn = wx.Button(panel, -1, "Just for fun...") # bind the button events to handlers self.Bind(wx.EVT_BUTTON, self.OnTimeToClose, btn) self.Bind(wx.EVT_BUTTON, self.OnFunButton, funbtn) # Use a sizer to layout the controls, stacked vertically and with # a 10 pixel border around each sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(text, 0, wx.ALL, 10) sizer.Add(btn, 0, wx.ALL, 10) sizer.Add(funbtn, 0, wx.ALL, 10) panel.SetSizer(sizer) panel.Layout() def OnTimeToClose(self, evt): """Event handler for the button click.""" print("See ya later!") self.Close() def OnFunButton(self, evt): """Event handler for the button click.""" print("Having fun yet?") class MyApp(wx.App): def OnInit(self): frame = MyFrame(None, "Simple wxPython App") self.SetTopWindow(frame) print("Print statements go to this stdout window by default.") frame.Show(True) return True if __name__ == '__main__': app = wx.GetApp() if app is None: app = MyApp(redirect=False, clearSigInt=False) else: frame = MyFrame(None, "Simple wxPython App") app.SetTopWindow(frame) print("Print statements go to this stdout window by default.") frame.Show(True) try: from IPython.lib.inputhook import enable_gui enable_gui('wx', app) except ImportError: app.MainLoop()now this code: will run IPython in a .py script on the cgi-server #!/usr/bin/env python3 import cgitb cgitb.enable import IPython IPython.start_ipython(argv=[]) I hope we still can have an open mind about this being fun and useful structure to run interactive web gui scripting which would be a PLUS... and this becomes a complicated question: b/c sudo IPython /var/www/cgi-bin/lftr/wxgui.py --gui=wx can be run as something like this: sudo python3 /var/www/cgi-bin/lftr/wxgui.py if it is including some IPython ---- #!/usr/bin/env python3 import cgitb cgitb.enable import IPython IPython.start_ipython(argv=[]) # this will start IPython, however i am unsure how to input the entire script import IPython.display #this will access display for a gui of wx hopefully gui=wx #incorrect code import wx class MyFrame(wx.Frame): """ This is MyFrame. It just shows a few controls on a wxPanel, and has a simple menu. """ def __init__(self, parent, title): wx.Frame.__init__(self, parent, -1, title, pos=(150, 150), size=(350, 200)) # Create the menubar menuBar = wx.MenuBar() # and a menu menu = wx.Menu() # add an item to the menu, using \tKeyName automatically # creates an accelerator, the third param is some help text # that will show up in the statusbar menu.Append(wx.ID_EXIT, "E&xit\tAlt-X", "Exit this simple sample") # bind the menu event to an event handler self.Bind(wx.EVT_MENU, self.OnTimeToClose, id=wx.ID_EXIT) # and put the menu on the menubar menuBar.Append(menu, "&File") self.SetMenuBar(menuBar) self.CreateStatusBar() # Now create the Panel to put the other controls on. panel = wx.Panel(self) # and a few controls text = wx.StaticText(panel, -1, "Hello World!") text.SetFont(wx.Font(14, wx.SWISS, wx.NORMAL, wx.BOLD)) text.SetSize(text.GetBestSize()) btn = wx.Button(panel, -1, "Close") funbtn = wx.Button(panel, -1, "Just for fun...") # bind the button events to handlers self.Bind(wx.EVT_BUTTON, self.OnTimeToClose, btn) self.Bind(wx.EVT_BUTTON, self.OnFunButton, funbtn) # Use a sizer to layout the controls, stacked vertically and with # a 10 pixel border around each sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(text, 0, wx.ALL, 10) sizer.Add(btn, 0, wx.ALL, 10) sizer.Add(funbtn, 0, wx.ALL, 10) panel.SetSizer(sizer) panel.Layout() def OnTimeToClose(self, evt): """Event handler for the button click.""" print("See ya later!") self.Close() def OnFunButton(self, evt): """Event handler for the button click.""" print("Having fun yet?") class MyApp(wx.App): def OnInit(self): frame = MyFrame(None, "Simple wxPython App") self.SetTopWindow(frame) print("Print statements go to this stdout window by default.") frame.Show(True) return True if __name__ == '__main__': app = wx.GetApp() if app is None: app = MyApp(redirect=False, clearSigInt=False) else: frame = MyFrame(None, "Simple wxPython App") app.SetTopWindow(frame) print("Print statements go to this stdout window by default.") frame.Show(True) try: from IPython.lib.inputhook import enable_gui enable_gui('wx', app) except ImportError: app.MainLoop()anyone? - - - for a round of direction or help??? i still get the display error no matter what so I set the Display Environment variable to localhost:0 with no noticible effect. RE: WxPython in web with a cgi server - jttolleson - Mar-05-2019 I suppose I am now working on an x display....so ipython will function for me: This is generally what I will start with and try to bring back an update: export DISPLAY=:1 Xvfb :1 -screen 0 1600x1200x16 -fbdir /var/tmp & x11vnc -rfbport 443 -display :1 -bg -nopw -listen localhost -xkb I hope more research will move me forward. |