Python execute code in parent shell upon exit - python

I have a search program that helps users find files on their system. I would like to have it perform tasks, such as opening the file within editor or changing the parent shell directory to the parent folder of the file exiting my python program.
Right now I achieve this by running a bash wrapper that executes the commands the python program writes to the stdout. I was wondering if there was a way to do this without the wrapper.
Note:
subprocess and os commands create a subshell and do not alter the parent shell. This is an acceptable answer for opening a file in the editor, but not for moving the current working directory of the parent shell to the desired location on exit.
An acceptable alternative might be to open a subshell in a desired directory
example
#this opens a bash shell, but I can't send it to the right directory
subprocess.run("bash")

This, if doable, will require quite a hack. Because the PWD is passed from the shell into the subprocess - in this case, the Python process, as a subprocess owned variable, and changing it won't modify what is in the super program.
On Unix, maybe it is achievable by opening a detachable sub-process that will pipe keyboard strokes into the TTY after the main program exits - I find this the most likely to succeed than any other thing.

Related

bat script under python subprocess lost ability to write to file

I'm learning to use the subprocess module.
I'm trying to run a .bat script under subprocess. The .bat script writes to a file every time it's called by double-clicking, but won't write to the same file when called from subprocess.
It's similar to this question, but in my case I'd much rather adapt the caller python script then the callee .bat script. The .bat is what I'm about to test.
My code follows. Path and name altered for brevity.
import subprocess
p=subprocess.Popen(r"path\foo.bat", shell=True, stdin = subprocess.PIPE, stdout = subprocess.PIPE)
p.communicate(input='\r\n')
I will need to fill in user input as the .bat runs, so (I think) I need to call Popen directly rather than using convenience functions. But other than that direct call I think the issue is not related, because the file writing should occur before the .bat's first need for user input.
Ommitting the communicate call or each of the arguments to Popen were tried and failed.
How can I change my python script to give the .bat file-writing privileges?
The obvious security implications are not relevant to my use case, the .bat is trusted.
EDIT: when implementing Rptk99's suggestion I've noticed that I can replace the path to the .bat with any string (literally, I've tried "hjklhjilhjkl"), and I'll get the same behaviour: the python prompt becomes interactive again. So I have a more fundamental problem: I cannot see any errors returned from the call.

How do i do sub processes properly with Python

I am new to python so I'm in the early stages of learning it. I was wondering if anyone knows how to run a system command after another. It's hard to explain:
subprocess.call('dir',shell=True)
subprocess.call('cd ..',shell=True)
subprocess.call('dir',shell=True)
When I run the command I expect to see the directory which the file is run. Which was fine.
Then the second process I expect to go up a directory.
Then the third command I expected to see the higher directory. Which I didn't I just saw the first directory.
Could some one explain why it isn't working as I expected and what I should do to correct it.
The general rule is that children cannot affect the parent's environment.
subprocess.call creates a child process. The child process can do many things. But, any changes it makes to the current working directory or to environment variables only last for the duration of the subprocess call. After the call completes and control returns to the parent, the parent's environment is restored unchanged.
If you want the cd to affect the next dir command, you need to have both in the same child. For example:
subprocess.call('cd ..; dir', shell=True)
You probably asked this question for more general purposes. But, for the specific examples that you provided, note that those actions might be better performed with the os module, rather than the subprocess module: listing files in the current directory can be done with os.listdir and changing the current working directory can be done with os.chdir
If you are trying to change the working directory in python that can be accomplished simply by os module. You can find that documentation here. I would suggest only using subprocess.call to call a script or another program that isn't trying to modify stuff based on the current environment.
When you run a subprocess with shell=True, python starts up a new shell to run the command in. It is basically the same as if python start up a new command prompt, entered in the command, and then closed the command prompt.
The consequence is that any action which only affects the shell is lost when the shell is closed. So you can create files and you'll see that because the hard drive is changed. But if you change the current directory of the shell that change will be lost.
You might wonder about the output of the program. Basically, the default is for the output of the program to be copied to the output of the calling program. (You can override this.)
If you want to change the current directory you want os.chdir. In general, you should avoid calling subprocesses and prefer python's tools. For example, instead of dir use os.listdir.

Executing some simple command in Command prompt using Python

I need to execute the simple command below in windows 7 command prompt using Python26.
cd C:\Python26\main project files\Process
C:\Aster\runtime\waster Analysis.comm
It runs a FEM simulation and I tried it manually and it worked well. Now, I want to automate the write procedure using Python26.
I studied the other questions and found that the os.system works but it didn't. Also I saw subprocess module but it didn't work.
The current directory is a process property: Every single process has its own current directory. A line like
os.system("cd xyz")
starts a command interpreter (cmd.exe on Windows 7) and execute the cd command in this subprocess, not affecting the calling process in any way. To change the directory of the calling process, you can use os.chdir() or the cwd keyword parameter to subprocess.Popen().
Example code:
p = subproces.Popen(["C:/Aster/runtime/waster", "Analysis.comm"],
cwd="C:/Python26/main project files/Process")
p.wait()
(Side notes: Use forward slashes in path names in Python files. You should avoid os.system() and passing shell=True to the function in the subprocess module unless really necessary.)

Change current working directory in command prompt using python

I am trying to write a python script that will change my cwd to the desired directory. I was not able to do this task directly from python so I wrote a simple batch script to do that.
Changedir.bat
#echo off
chdir /D F:\cygwin\home\
If I execute the above script directly in my cmd it works fine but if I try to execute it with a python script nothing happens. My cwd remains same.
PythonScript.py
import shlex,subprocess
change_dir = r'cmd.exe /c C:\\Users\\test.bat'
command_change = shlex.split(change_dir)
subprocess.call(command_change)
Of course this can't work, because subprocess.call is spawning whole new process for your script. This executes the script in a completely separate environment.
If you want to change directory in the command prompt you have to use either cd or a .bat script.
You can't get another process (i.e. Python) to do it because changes to the current directory, made in another process are not reflected back to the parent process. The reason the .bat script works is that it is processed by the command shell that invokes it rather than by a child process.
You could try this. It works in Linux to change the CWD of the current shell. It is horrible.
def quote_against_shell_expansion(s):
import pipes
return pipes.quote(s)
def put_text_back_into_terminal_input_buffer(text):
# use of this means that it only works in an interactive session
# (and if the user types while it runs they could insert
# characters between the characters in 'text')
import fcntl, termios
for c in text:
fcntl.ioctl(1, termios.TIOCSTI, c)
def change_shell_working_directory(dest):
put_text_back_into_terminal_input_buffer("cd "+quote_against_shell_expansion(dest)+"\n")

python + windows: run exe as if it's unrelated to the current process

I know I can use subprocess.Popen to run an executable, and potentially redirect stdin and stdout to files / using pipes to my process. Is there a way to run an executable such that the spawned process has no relation to the current Python process, however? Meaning, I want to start a process in the same way as if I would double-click on the .exe, or type in its name into Start->Run...
On Windows, see os.startfile().

Categories