Is there a way in Python to launch a Tcl shell or a unix shell and take control of it to perform operations? I understand that the subprocess, TkInter can be used to execute shell/Tcl scripts and get the output.
Specifically this will be a wrapper on the Tcl shell/tool that will control its stdin/out. I have tried establishing a client-server connection but in order for python to control tcl shell, the connection needs to be established manually. What should be approach here?
With Tkinter, you have a Tcl interpreter inside the same process as Python. That's fine for doing conventional stuff (or Tk) but if you've got some sort of custom Tcl interpreter to control, you'll probably want to launch that as a subprocess connected by pipes to the parent Python process.
The subprocess module in Python has most of what you'll need.
import subprocess
p = subprocess.Popen(["tclimplementation"], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
# Turn off buffering on the Tcl side
print("fconfigure stdout -buffering none", file=p.stdin)
# Also should read from p.stdout; here's how
line = p.stdout.readline().strip()
That telling of the Tcl side to fconfigure stdout -buffering none is important, as Tcl (in common with most processes) defaults to buffering multiple kilobytes when writing to anything other than a terminal (great for performance, not great for interactive use).
Now that you can send messages back and forth, you need to think more about how to actually control the other side. That's rather application specific.
Related
Tools like sudo read from /dev/tty to read a password.
I would like to avoid this.
The subprocess should not be able to read /dev/tty. The subprocess should fail immediately instead of waiting for input for ever.
I am using the subprocess module of Python. The subprocess should fail if it tries to read from /dev/tty.
Remember: The tool sudo is just an example. A fancy command line argument to sudo does not solve my problem. This should work for all linux command line tools.
Question: How to make any tool fail as soon as it wants to read from /dev/tty (called via the subprocess module of Python)?
Background: This is a normal linux user process, not root.
Since python3.2 Popen takes an argument start_new_session which will cause the executed process to be started detached from the current controlling terminal by calling setsid() prior to executing the child process.
So all you should need is to start the process with start_new_session=True
I am trying to launch a program/GUI from within a python code.
From the terminal, I can get the program to launch by simply typing the program name. A few lines get outputted to the terminal, and then a separate window opens with the GUI.
I tried to emulate this in python by running
os.system("<program name>")
The typical output lines, as mentioned above, get printed to the console, but no window opens up with the GUI.
Can os.system() be used to execute programs that have their own separate window?
From the Python manual:
[os.system] is implemented by calling the Standard C function
system()
That being said, you shouldn't have any problems launching a GUI application with os.system. I've just tried it myself and it works fine.
It also mentions in the manual that:
The subprocess module provides more powerful facilities for spawning
new processes and retrieving their results; using that module is
preferable to using this function.
Maybe that's worth a try. Do any other GUI applications work when you spawn them with os.system?
Here is a solution using subprocess
import subprocess
subprocess.Popen("notepad.exe")
Or if you want to run a python program with a specific interpreter:
subprocess.Popen('{0} {1}'.format(PythonInterpreterPath,PythonFilePath.py))
Is there any way of attaching a console's STDIN/STDOUT to an already running process?
Use Case:
I have a python script which runs another python script on the command line using popen.
Let's say foo.py runs popen to run python bar.py.
Then bar.py blocks on input. I can get the PID of python bar.py. Is there any way to attach a new console to the running python instance in order to be able to work interactively with it? This is specifically useful because I want to run pdb inside of bar.py.
No way. But you can modify the way you start bar.py in order to be prepared to take over stdin and stdout.
A simple method would be to just create named pipes and supply these as stdin/stdout in the Popen call. You may then connect to these pipes from you shell (exec <pipe1 >pipe2) and interact. This has the disadvantage that you must connect to the pipes to see what the process is doing. While you can work around that by using tee on a log file, depending on the terminal capability demands of bar.py this kind of interaction may not be the greatest pleasure.
A better way could be to incorporate a terminal multiplexer like GNU screen or tmux into you process tree. These tools can create a virtual terminal in which the application is run. You may then at any time attach and detach any other terminal to this terminal buffer. In your specific case, foo.py would run screen or tmux, which will run python bar.py in a complete (VT100) terminal emulation. Maybe this will solve your problem.
You cannot redirect stdin or stdout for a running process. You can, however, add code to your caller -- foo.py -- that will read from foo.py's stdin and send it to bar.py's stdout, and vice-versa.
In this model, foo.py would connect bar.py's stdin and stdout to pipes and would be responsible for shuttling data between those pipes and the real stdin/stdout.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Running a process in pythonw with Popen without a console
How do I eliminate Windows consoles from spawned processes in Python (2.7)?
I am using Python 2.7 and running the python scripts from within IDLE.
The commands I am executing are simple exe's that perform quick tasks. The issue I am having is every time the external commands are called from within Python a console is created and it flashes on my screen and takes focus, thus preventing me from using my PC while executing various scripts.
Examples of how I am calling them from within Python are as follows:
result = call(["Commands\Set.exe", str(i), ARG2])
check_output(["Commands\Read.exe", ARG2])
Searching for a solution I came across adding the following
shell=True
to make the following command
check_output(["Commands\Read.exe", ARG2], shell=True)
However I still get the console appear every time an external command is called
There might be two issues here. First off, if your python scripts have the .pyw extension then they will be associated with pythonw which does not use a console*. However, you have shell=True, which generates a console*. You need to run the program and hide the console:
import subprocess
proc = subprocess.Popen('hello.py', creationflags=subprocess.SW_HIDE, shell=True)
proc.wait()
*Pedantically, it's not a dos prompt, it is a console window. DOS - Disk Operating System - was an IBM mainframe OS. MS-DOS or PC-DOS command-line features were mirrored (with a lot of extra features) by cmd.exe (a Windows shell), which is a console program and so uses a console window. It's that console window you need to hide.
You need to use startupinfo parameter of subprocess.Popen() class' constructor.
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
startupinfo.wShowWindow = subprocess.SW_HIDE
subprocess.Popen(command, startupinfo=startupinfo)
You do not need shell=True if all you want is to hide console window; see this answer.
I need to write a Python script that can run another command line program and interact with it's stdin and stdout streams. Essentially, the Python script will read from the target command line program, intelligently respond by writing to its stdin, and then read the results from the program again. (It would do this repeatedly.)
I've looked through the subprocess module, and I can't seem to get it to do this read/write/read/write thing that I'm looking for. Is there something else I should be trying?
To perform such detailed interaction (when, outside of your control, the other program may be buffering its output unless it thinks it's talking to a terminal) needs something like pexpect -- which in turns requires pty, a Python standard library module that (on operating systems that allow it, such as Linux and Mac OS x) implements "pseudo-terminals".
Life is harder on Windows, but maybe this zipfile can help -- it's supposed to be a port of pexpect to Windows (sorry, I have no Windows machine to check it on). The project in question, called wexpect, lives here.
see the question
wxPython: how to create a bash shell window?
there I have given a full fledged interaction with bash shell
reading stdout and stderr and communicating via stdin
main part is extension of this code
bp = Popen('bash', shell=False, stdout=PIPE, stdin=PIPE, stderr=PIPE)
bp.stdin.write("ls\n")
bp.stdout.readline()
if we read all data it will get blocked so the link to script I have given does it in a thread. That is a complete wxpython app mimicking bash shell partially.