Skip to content

Python-Shell Output not working as needed #263

Description

@Shahi-Paneer

I am trying to set up a website for my school where users can run some python code and the executing part of the code is working fine but, the only problem is that python-shell waits for the code to be complete then send-out the output.

What current output looks like:

2

What I am trying to achieve
3
:

Python-Shell config:

let {
  PythonShell
} = require('python-shell')

var run = 1;
pyshell: PythonShell
constructor(); {
  this.pyshell = new PythonShell(__dirname + "/physics.py")
  pythonPath: '/usr/bin/python3';
  pythonOptions: ['i', ]



  if (run == 1) {

    socket.on("hello", function(pyinput2) {

      var input = pyinput2
      console.log(input, "sending");
      this.pyshell.send(input)
      console.log(input, "sent")

    });


  }

  this.pyshell.on("message", (...args) => {
    console.log(args)
    socket.send(args)
    this.pyshell.end
  })

  this.pyshell.on('message', function(message) {
    // received a message sent from the Python script (a simple "print" statement)
    console.log(message + "\n");

  });

Here is the Python script im using for testing:

# Program make a simple calculator

# This function adds two numbers
def add(x, y):
    return x + y

# This function subtracts two numbers
def subtract(x, y):
    return x - y

# This function multiplies two numbers
def multiply(x, y):
    return x * y

# This function divides two numbers
def divide(x, y):
    return x / y


print("Select operation.")
print("1.Add")
print("2.Subtract")
print("3.Multiply")
print("4.Divide")

while True:
    # take input from the user
    choice = input("Enter choice(1/2/3/4): ")

    # check if choice is one of the four options
    if choice in ('1', '2', '3', '4'):
        num1 = float(input("Enter first number: "))
        num2 = float(input("Enter second number: "))

        if choice == '1':
            print(num1, "+", num2, "=", add(num1, num2))

        elif choice == '2':
            print(num1, "-", num2, "=", subtract(num1, num2))

        elif choice == '3':
            print(num1, "*", num2, "=", multiply(num1, num2))

        elif choice == '4':
            print(num1, "/", num2, "=", divide(num1, num2))
        
        # check if user wants another calculation
        # break the while loop if answer is no
        next_calculation = input("Let's do next calculation? (yes/no): ")
        if next_calculation == "no":
          break

I'm new to javascript so sorry if I lack some knowledge... any help would be greatly appreciated - Thanks

EDIT - Here is my full code:

Server.js

const app = require('express')();
const http = require('http').Server(app);
const io = require('socket.io')(http);
const {
	exec
} = require("child_process");
const {
	stdout
} = require('process');
// const { spawn } = require('child_process');
var async = require("async");



app.get('/', function(req, res) {
	res.sendfile('index.html');
});

//Whenever someone connects this gets executed
io.on('connection', function(socket) {
	console.log('A user connected');

	//Whenever someone disconnects this piece of code executed
	socket.on('disconnect', function() {
		console.log('A user disconnected');

	});
});

io.sockets.on('connection', function(socket) {
	socket.on('message', function(message) {
		// console.log(message,);
	});

	var data = 1

	socket.on('my other event', function(data) {
		// console.log(data);

		var command = JSON.stringify(data)
		console.log(command)

		console.log(command)


		/*    var options = {
		      mode: 'text',
		      pythonPath: '/usr/bin/python',
		      pythonOptions: ['-u',],
		      // make sure you use an absolute path for scriptPath
		      scriptPath: '/home/compile',
		      //args: ['value1', 'value2', 'value3']
		    };

		    PythonShell.run('physics.py', options, function (err, results) {
		      this.pyshell.send("1")
		      this.pyshell.send("2")
		      this.pyshell.send("3")
		      this.pyshell.send("no")
		      if (err) throw err;
		      // results is an array consisting of messages collected during execution
		      console.log('results: %j', results);
		    }); */


		let {
			PythonShell
		} = require('python-shell')

		var run = 1;
		pyshell: PythonShell
		constructor(); {
			this.pyshell = new PythonShell(__dirname + "/physics.py")
			pythonPath: '/usr/bin/python3';
			pythonOptions: ['i', ]



			if (run == 1) {

				socket.on("hello", function(pyinput2) {

					var input = pyinput2
					console.log(input, "sending");
					this.pyshell.send(input)
					console.log(input, "sent")

				});


			}

			this.pyshell.on("message", (args) => {
				console.log(args + "hi")
				socket.send(args)
				this.pyshell.end
			})

			this.pyshell.on('message', function(message) {
				// received a message sent from the Python script (a simple "print" statement)
				console.log(message + "hello\n");

			});
			/* this.pyshell.end((err, code, signal) => {
			   console.log("The error was: " + err)
			   console.log("The exit code was: " + code)
			   console.log("The exit signal was: " + signal)
			   console.log("finished")
			 }) */
		}


	});
});



io.sockets.on('connection', function(socket) {
	socket.on('clicked', function(msg) {
		// console.log("button clicked");

		var pyinput2 = msg

		var input = ''
		var input = JSON.stringify(pyinput2)
		// console.log(input, "is this input?")
		var run = 0

	});

	socket.on('run', function(hello) {

		var run = 1
		console.log(run)

		/*if (run == 0) {

		   run = 1
		   console.log(run)

		} else if (run == 1) {


		   run = 0
		   console.log(run)

		} */


	});





});

var go = 1

if (go == 1) {

	let {
		PythonShell
	} = require('python-shell')


	pyshell: PythonShell
	constructor(); {
		this.pyshell = new PythonShell(__dirname + "/physics.py")
		//pythonOptions: ['i',]
		this.pyshell.send("1")
		console.log("sent1")
		this.pyshell.send("2")
		console.log("sent2")
		this.pyshell.send("3")
		console.log("sent3")

		this.pyshell.on("message", (args) => {
			console.log(args, "hello")
			this.pyshell.end
		})

	}


};


http.listen(8080, function() {
	console.log('listening on *:8080');
});

Here is index.html:

<!DOCTYPE html>
<html>
<style>
	body,
	html {
		margin-left: 1%;
		margin-right: 1%;
		margin-bottom: 1%;
		margin-top: 1%;
		width: 98%;
		height: 98%;
	}
</style>

<head>
	<title>LC</title>

</head>
<script src="/socket.io/socket.io.js"></script>

<script src="https://cdn.jsdelivr.net/npm/jquery@3.3.1/dist/jquery.min.js"></script>
<script src='https://cdn.jsdelivr.net/xterm/2.3.2/xterm.js' type="text/javascript"></script>

<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/fomantic-ui@2.8.8/dist/semantic.min.css">
<script src="https://cdn.jsdelivr.net/npm/fomantic-ui@2.8.8/dist/semantic.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/xterm/2.3.2/xterm.css" />
<script>
	const socket = io();
</script>

<body>

	<br />
	<h1 style="color: #2D2E2C"><em style="color: #5DA5D5">web</em></h1>

	<br />
	<! <input type="text" id="myText" value="Some text...">
		<! <button onclick="myFunction()"></button>
			<div class="ui input"><input type="text" id="input" value=""> </div>
			<button class="ui primary button" onclick="input()">input</button>
			<button class="ui button" onclick="run()">run</button>



			<script>
				function run() {


					socket.emit('run')
					socket.send(run)

				}


				function input() {

					var pyinput = ''

					var pyinput = document.getElementById("input").value;


					//socket.emit('clicked', pyinput);



				}
			</script>

			<p id="demo"></p>

			<script type="text/javascript">
				var lol = 1
				var data = 'poopy was here'

				function myFunction() {
					var lol = document.getElementById("myText").value;
					document.getElementById("demo").innerHTML = lol;
				}


				//socket.emit('my other event', { lol });
			</script>



			<script>
				function pooFunction() {

					var lol = document.getElementById("myText").value;

					//socket.emit('my other event',  lol );


					socket.send('hi');


				}


				socket.emit('my other event', {
					my: data
				});

				socket.on('message', function(message) {
					console.log(message);
					var out = message
					document.getElementById("out").innerHTML = out;
				});
			</script>




			<p id="out"></p>

			<div id="terminal"></div>
			<script>
				var term = new Terminal({
					cursorBlink: "block"
				});
				term.open(document.getElementById('terminal'));


				var curr_line = "";
				var entries = [];
				// term.open(document.getElementById("terminal"));
				term.write("web shell $ ");


				//term.write('Hello from lollolol \x1B[1;3;31mxterm.js\x1B[0m $ ')
				socket.on('message', function(message) {
					console.log(message);
					var out = JSON.stringify(message)
					term.write(out + "\r\n")
				});

				term.prompt = () => {
					if (curr_line) {
						let data = {
							method: "command",
							command: curr_line
						};
						ws.send(JSON.stringify(data));
					}
				};

				term.prompt();
				// term.write("web shell $ ");

				// Receive data from socket


				term.on("key", function(key, ev) {
					//Enter
					if (ev.keyCode === 13) {
						if (curr_line) {
							entries.push(curr_line);
							console.log(curr_line)
							socket.emit('hello', curr_line);
							term.write("\r\n");
							curr_line = "";
							term.write("web shell $ ");

							term.prompt();
						}
					} else if (ev.keyCode === 8) {
						// Backspace
						if (curr_line) {
							curr_line = curr_line.slice(0, curr_line.length - 1);
							term.write("\b \b");
						}
					} else {
						curr_line += key;
						term.write(key);
					}
				});
			</script>

</body>

</html>

List of dependencies:

  "dependencies": {
    "express": "^4.17.3",
    "jquery": "^3.6.0",
    "linerstream": "^0.2.0",
    "python-shell": "^3.0.1",
    "xterm": "^4.18.0"
  },
  "devDependencies": {
    "socket.io": "^4.4.1"
  }

Also I am running this on a centos server and have also tested it on fedora server, behavior occurred on both machines.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions