Docker accepting input to python script - python

I am simulating an online IDE using docker.
Each time user submits their code, an image will be generated and be run. It is working as expected, however when the code asks for input e.g
print("Begin script")
x = input("Enter your name")
print("you entered")
print(x)
python code to run docker:
container = subprocess.Popen(["docker", "run","-it", "--rm", "--name",imageName,imageName])
I am unable to pass in input to the python script.
It does not even print the prompt "Test input" into terminal
I have tried using docker attach command, and I am enter able to enter into terminal, but it is not sending input to python script

Via comments:
subprocess.run(["docker", "run","-ti", "--rm", "--name",imageName,imageName], capture_output=True)
You're using a function that is described to (emphasis mine)
Run the command described by args. Wait for command to complete, then return a CompletedProcess instance.
You also say
it does not even print the prompt of the input message
This is because you've explicitly told subprocess.run() to capture the output instead of allowing it to be printed to stdout. If you were to print the return value of that call, you'd possibly see the output.
If you just want some static input to be piped to the process and get the output, you could use
proc = subprocess.run(..., input="123\n", capture_output=True)
print(proc.stdout)
to simulate someone entering 123 and a newline.
If you want an interactive experience, you will need to use subprocess.Popen() instead. Wiring the stdin/stdout/stderr pipes is somewhat tricky, especially if you need a TTY-like experience.

I am really sorry that it doesn't answer your question directly, but I am sure it would help.
I think you are trying to make an entire docker container for every user. You don't strictly need that if you only plan to allow them to use your service as a simple IDLE.
You could use something like socat or xinetd to achieve the same.
Here is an example that uses socat to run a python script for anyone who connects to the server: https://gitlab.com/Milkdrop/xmas-2020/-/tree/master/misc/complaint
Also, I recommend AGAINST using exec() or eval() to allow others to execute code on your system. Actually, you should not use them in general either.

Related

How to set or modify breakpoint commands in a gdb python script

In a gdb python script, how do I set or modify the commands list for a breakpoint?
I can do this trivially by hand. For example to change the commands list for breakpoint 2, at the prompt I can enter:
(gdb) commands 2
Type commands for breakpoint(s) 2, one per line.
End with a line saying just "end".
>info reg rax
>set $rax=0x1234
>end
Yet, from a gdb python script I cannot seem to execute a multiline command.
gdb.execute("commands 2\ninfo reg rax\nset $rax=0x1234\nend\n")
Just gets me an output like
(gdb) source blah.py
>
and it is sitting there for more input. It won't move on until I type end and press enter. Then it just gives complaints making it clear it has not correctly parsed anything after the commands 2 of that string.
Trying to input each line separately doesn't help. For example the script:
gdb.execute("commands 2")
gdb.execute("info reg rax")
gdb.execute("set $rax=0x1234")
gdb.execute("end")
waits for more input from the user during the first execute, and so has similar problems. And while mostly wishful, the following doesn't work either:
gdb.execute(["commands 2","info reg rax","set $rax=0x1234","end"])
It is easy to programatically get the list of breakpoints with gdb.breakpoints(). And these objects have a property commands, which I can see any commands I set by hand or from a native gdb script. However if I try to modify this property, it fails. So once something is set by hand, or a gdb script, there appears to be no way for a python script to edit it. The API document is missing a lot of helpful information, but it does state https://sourceware.org/gdb/onlinedocs/gdb/Breakpoints-In-Python.html#Breakpoints-In-Python Variable: Breakpoint.commands ... This attribute is not writable.
And no, I don't consider it a useful answer to "never use gdb scripts" or "never enter commands by hand" and "instead always write a python gdb.Breakpoint subclass with Breakpoint.stop() set to do something special, and rewrite all existing scripts to use such features". I can only seem to find information for that workaround. But I'm not willing to give up current methods of interaction just due to a gdb quirk.
Since I can easily run commands to do what I want by hand, there must be a way to modify or set the breakpoint commands from a gdb python script. How do I do this?
I don't think there is a way at present.
As you found, gdb.execute doesn't support multiple lines. This is just a limitation in the Python layer that nobody ever fixed. (I didn't see a bug for it so I filed bug 22730.
Also, a breakpoint's commands field is not assignable. I filed bug 22731 for this.
Your source idea, while horrible, would work fine.

Automatically restart a Python program if it's killed

I run a Python Discord bot. I import some modules and have some events. Now and then, it seems like the script gets killed for some unknown reason. Maybe because of an error/exception or some connection issue maybe? I'm no Python expert but I managed to get my bot working pretty well, I just don't exactly understand how it works under the hood (since the program does nothing besides waiting for events). Either way, I'd like it to restart automatically after it stops.
I use Windows 10 and just start my program either by double-clicking on it or through pythonw.exe if I don't want the window. What would be the best approach to verify if my program is still running (it doesn't have to be instant, the verification could be done every X minutes)? I thought of using a batch file or another Python script but I have no idea how to do such thing.
Thanks for your help.
You can write another python code (B) to call your original python code (A) using Popen from subprocess. In python code (B), ask the program to wait for your python code (A). If 'A' exits with an error code, recall it from B.
I provide an example for python_code_B.py
import subprocess
filename = 'my_python_code_A.py'
while True:
"""However, you should be careful with the '.wait()'"""
p = subprocess.Popen('python '+filename, shell=True).wait()
"""#if your there is an error from running 'my_python_code_A.py',
the while loop will be repeated,
otherwise the program will break from the loop"""
if p != 0:
continue
else:
break
This will generally work well on Unix / Windows systems. Tested on Win7/10 with latest code update.
Also, please run python_code_B.py from a 'real terminal' which means running from a command prompt or terminal, and not in IDLE.
for problem you stated i prefer to use python subprocess call to rerun python script or use try blocks.
This might be helpful to you.
check this sample try block code:
try:
import xyz # consider it is not exist or any error code
except:
pass # go to next line of code to execute

Not able to find file using ssh on another server using python pexpect on linux

I created the simple python script using pexpect, created one spwan process using
CurrentCommand = "ssh " + serverRootUserName + "#" + serverHostName
child = pexpect.spawn(CurrentCommand)
Now I am running some command like ls-a or "find /opt/license/ -name '*.xml'"
using code
child.run(mycommand)
it works fine if running from Pycharm but if running from terminal it is not working it is not able to find any file, I think it is looking into my local system.
Can anyone suggest me something. Thanks
As a suggestion, have a look at the paramiko library (or fabric, which uses it, but has a specific purpose), as this is a python interface to ssh. It might make your code a bit better and more resilient against bugs or attacks.
However, I think the issue comes from your use of run.
This function runs the given command; waits for it to finish; then returns all output as a string. STDERR is included in output. If the full path to the command is not given then the path is searched.
What you should look at is 'expect'. I.e. your spawn with spawn then you should use expect to wait for that to get to an appropiate point (such as connected, terminal ready after motd pushed etc (because ouy might have to put a username and password in etc).
Then you want to run sendline to send a line to the program. See the example:
http://pexpect.readthedocs.io/en/latest/overview.html
Hope that helps, and seriously, have a look at paramiko ;)

Override raw_input to get answer from remote client

I'm trying to override the standard raw_input so I can have a "remote raw_input".
What I need is to implement this overriden raw_input so when I use it on my server, it will open a message box in the remote client's computer and wait for his answer. After getting the response, I'll then be able to continue with my program.
I've been searching a lot about how I can do this, but I'm a little lost mostly because I'm new to python.
And I have to do this with raw_input, is that possible? Can someone give me a little guidance?
UPDATE:
One good example of what I'm trying to achieve is how Jupyter handles raw_inputs.
In this notebook I simply run a raw_input, then Jupyter creates a textbox and waits for my answer:
And then after I type my answer it goes on with the code:
So how does Jupyter get 'in the middle' of the raw_input to create a textbox and wait for the user input?
Overriding builtins is, generally, not recommended for a number of reasons. Instead, try something like the following, using receive_input instead of raw_input.
SERVER = 1
CLI = 2
...
config.input_type = CLI # in cli code, or SERVER in server code
...
def receive_input(cfg):
if cfg.input_type == CLI:
return raw_input()
elif cfg.input_type == SERVER:
# retrieve from somewhere else
Jupyter likely scans the AST of the input for raw_input called as a function and replaces that with their implementation.

Multiple terminal handling in python

I have a python application which i want to purpose as a multi as a multi terminal handler, i want each object to have it's own terminal separated from the rest each running it's own instance, exactly like when i run two or more separate terminals in Linux (/bin/sh or /bin/bash)
sample: (just logic not code)
first_terminal = terminalInstance()
second_terminal = terminalInstance()
first_result = first_terminal.doSomething("command")
second_result = second_terminal.doSomething("command")
i actually need to have each terminal to grab a stdin & stdout in a virtual environment and control them, this is why they must be seperate, is this possible in python range? i've seen alot of codes handling a single terminal but how do you do it with multiple terminals.
PS i don't want to include while loops (if possible) since i want to add scalability from dealing with 2 or more terminals to as much as my system can handle? is it possible to control them by reference giving each terminal a reference and then calling on that object and issuing a command?
The pexpect module (https://pypi.python.org/pypi/pexpect/), among others, allows you to launch programs via a pseudo-tty, which "allows your script to spawn a child application and control it as if a human were typing commands."
You can easily spawn multiple commands, each running in a separate pseudo-tty and represented by a separate object, and you can interact with each object separately. There is a lot of flexibility as to when/how you interact. You can send input to them, and read their output, either blocking or non-blocking, and incorporating timeouts and alternative outputs.
Here's a trivial session example (run bash, have it execute an "ls" command, gather the first line of output).
import pexpect
x = pexpect.spawn("/bin/bash")
x.sendline("ls")
x.expect("\n") # End of echoed command
x.expect("\n") # End of first line of output
print x.before # Print first line of output
Note that you'll receive all the output from the terminal, typically including an echoed copy of every character you send to it. If running something like a shell, you might also need to set the shell prompt (or determine the shell prompt in use) and use that in parsing the output (i.e. in finding the end of each command's output).

Categories

Resources