1

python3 -i test.py opens an interactive python shell after running test.py. However, if I try to run it in the background with python3 -i test.py & the job stops automatically with a ^C and shows

[4]+  Stopped                 python3 -i test.py

, and I can't access python's interactive shell (with the variables from test.py still in the environment) afterwards. fging the process (i.e. fg %4) leads to an interactive shell where my input can't be seen but is still run after pressing <Enter>. How do I run the interactive shell "normally" after running test.py in the background?

(For reference, test.py contains

from time import sleep
a = 'hello world'
for i in range(10):
    sleep(1)
    print(a)

and my shell looks like this:

$ python3 -i test.py &
[4] 6708
$ hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
fg %4
python3 -i test.py
>>> 'hello world'
>>>

and I typed a after being prompted by the first >>>, but it isn't shown. )

-- Edit @muru --

Sending it to the bg after running it normally in the fg gives:

$
$
$ python3 -i test.py
hello world
hello world
hello world
hello world
^Z
[4]+  Stopped                 python3 -i test.py
$ bg %4
[4]+ python3 -i test.py &
$ hello world
hello world
hello world
hello world
hello world
hello world
echo 'hello world'
hello world

[4]+  Stopped                 python3 -i test.py
$
$

where shell was expecting input and I typed echo 'hello world' after the 10 "Hello World"'s.

  • Why would an interactive process be run in the background? – muru Aug 18 '19 at 10:30
  • I want to run a python file that takes quite some time, and do other things with the same terminal in the meantime, but still examine the script’s environment (interactively) when it’s done running. – Anonymous Aug 18 '19 at 13:37
  • Try sending it to the background after starting it normally (Ctrl-Z then bg). – muru Aug 18 '19 at 14:46
0

That happens because the Python interpreter in background "competes" the prompt with the command-line shell as soon as it finishes executing the test.py program.

Naturally Python loses that "battle" because it is not the one allowed to go interactive at that moment. However it gets stopped a bit too late, enough to leave its own prompt in a state that will not resume cleanly on an fg command.

One way to settle this is by adding the following lines at the end of your Python program:

import os, signal  # access os-level functions and UNIX-signals
os.kill(os.getpid(), signal.SIGSTOP)  # send myself the UNIX SIGSTOP signal

(Of course the import can also be placed on top of your program as per typical practice.)

That os.kill() line will put the Python interpreter in stopped state, just like it gets when it tries to go interactive at the wrong moment. Only, this time it does it itself, before even attempting to prompt, so that it is not left in an inconsistent state.

You know when that os.kill() is reached because the command-line shell notifies you that Python got Stopped. An fg at that moment will resume Python making it proceed from the os.kill() line, thus starting its own interactive session.

Don't use bg to resume it after it got Stopped by that os.kill(), because doing so will only make the kernel stop Python again for attempting to go interactive while in background.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.