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.

3
  • Why would an interactive process be run in the background?
    – muru
    CommentedAug 18, 2019 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.
    – LHeng
    CommentedAug 18, 2019 at 13:37
  • Try sending it to the background after starting it normally (Ctrl-Z then bg).
    – muru
    CommentedAug 18, 2019 at 14:46

1 Answer 1

1

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.

    You must log in to answer this question.

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.