TCP Python Connection to VC - Processing Freeze

Hello Everybody,
I am currently running into a problem. I set up a python script outside of VC and I want to send data from there as a continious stream to VC to simulate real Data input via TCP with Python.

I set up a Server (external script) client (script in VC) setup that works perfectly fine outside of VC. In VC, the funcionality of the client is still given, but it freezes the screen and the simulation can not be seen by the user while the transmission is going on in the background (sometimes also the “processing” alert pops up). The script runs perfectily fine if used outside of VC

Is there a smart way to work around that/improve the performance? I guess it is a performance issue right? I tried to create a work around with non blocking or multi threading, but don´t seem to be executed the expected way in the stackless python environment.

Attached you can find the client code. The client receives a dictionary (pickeled) and a header with the given length of the transmission.

from vcScript import *
import sys
import pickle 
from datetime import datetime
import socket
import select

HEADERSIZE = 10

sim = getSimulation()
app = getApplication()

def OnStart():
  global s
  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  # Connect the socket to the port where the server is listening
  server_address = ('localhost', 4000)
  print('connecting to %s port %s' % server_address)

  ret = s.connect_ex(server_address) #BLOCKING

  if ret != 0:
    print('Non Blocking - failed to connect!')
  
  print('Non Blocking - connected!')
  s.setblocking(False)

def OnRun():  
  global s
  # Wait for incoming messages
  full_msg = b''
  new_msg = True
  inputs = [s]
  outputs = [s]

  print("Waiting for Input from Server Python Script in Jupyter Hub")

  while inputs:
    # print("Waiting for Input from Server") 
    readable,writable,exceptional = select.select(inputs,outputs,inputs,0.1)
    
    #for s in writable:
     # pass
      
    for s in readable:
      
      msg = s.recv(1024)
        
      if new_msg:
        if msg != b'':
          msglen = int(msg[:HEADERSIZE])
          # print(f"new message length:{msg[:HEADERSIZE]}"
          new_msg = False
        else:
          inputs.remove(s)
          s.close()
          print ("Socket wurde geschlossen")
          break
      full_msg += msg
      
      if len(full_msg) - HEADERSIZE == msglen:
        #print("full msg recvd")
        # print(full_msg[HEADERSIZE:])
        
        d = pickle.loads(full_msg[HEADERSIZE:])
        #print datetime.now()
        print (d)
        
      new_msg = True
      full_msg = b''
      
    for s in exceptional:
      print('Non Blocking - error')
      inputs.remove(s)
      outputs.remove(s)
      break

My guess is that you are actually constantly blocking the VC main thread (which is the only thread, really) by waiting on data to be received on the socket.

Also note that the print command in VC is also quite slow to execute.

Thanks for the quick reply! Yeah I came to the same conclusion, do you have any additional input how to work around this issue? If I set the time to real time, the simulation get fast forwarded to the point where the data stream ends. I want to visualize some real time data, so the screen “not freezing” would be the main key to the success of my program.

I also tried to work without print comments, the main problem seems to be the recv blocking while there is no data send and the non blocking logic doesnt really work on the VC stackless python. My server sends a set of data every X seconds, in between the sockte is open, but no data is being send.

Thanks!

Well, seems that successful examples of socket communication from VC python scripts have used combination of non-blocking mode, SOCK_DGRAM, and recvFrom in a loop with simulation-time delay() on exception instead of the SOCK_STREAM and select approach you have.

The delay() call within OnRun() yields the coroutine so simulation thread can do all the other stuff.

The delay() part is the one I didnt think about including. I had a delay included in my server script, but not on the VC side. This changed a whole lot and the sim is running more or less smooth now. Thanks a lot!