[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

[2.4.2/Linux] Getting Python to fork?

unknown

2/4/2008 2:52:00 AM

Hello

I need to launch a Python script, and fork it so that the calling
script can resume with the next step will the Python script keeps
running.

I tried those two, but they don't work, as the calling script is stuck
until the Python script ends:

sys.stdout = open(os.devnull, 'w')

=====
#if os.fork():
pid = os.fork()
if pid > 0:
sys.exit(0)
=====

Should I use another library to do this?

Thank you.
12 Answers

Gary Herron

2/4/2008 5:55:00 AM

0

Gilles Ganault wrote:
> Hello
>
> I need to launch a Python script, and fork it so that the calling
> script can resume with the next step will the Python script keeps
> running.
>
> I tried those two, but they don't work, as the calling script is stuck
> until the Python script ends:
>
> sys.stdout = open(os.devnull, 'w')
>
> =====
> #if os.fork():
> pid = os.fork()
> if pid > 0:
> sys.exit(0)
> =====
>
> Should I use another library to do this?
>
> Thank you.
>
What OS? Stuck how? I you want both processes to execute, why do you
call sys.exit? I don't think you've shown enough code to tell what you
are doing right or wrong. Try this:

pid = os.fork()
if pid:
# Original fork continues here
# pid is child's process id
# ... so onwards with the next step
# If it needs to wait for the child to complete, it can call os.waitpid
else:
# New fork continues here, independently of the original process
# doing whatever the fork was create for

Gary Herron





Jon Ribbens

2/4/2008 2:30:00 PM

0

On 2008-02-04, Gilles Ganault <nospam@nospam.com> wrote:
> I need to launch a Python script, and fork it so that the calling
> script can resume with the next step will the Python script keeps
> running.
>
> I tried those two, but they don't work, as the calling script is stuck
> until the Python script ends:

This should work I believe:

if os.fork():
os._exit(0)
os.setsid()
os.chdir("/")
fd = os.open("/dev/null", os.O_RDWR)
os.dup2(fd, 0)
os.dup2(fd, 1)
os.dup2(fd, 2)
if fd > 2:
os.close(fd)
# do stuff

Although bear in mind it's pretty UNIX-y.

Christian Heimes

2/4/2008 2:41:00 PM

0

Jon Ribbens wrote:
> This should work I believe:
>
> if os.fork():
> os._exit(0)
> os.setsid()
> os.chdir("/")
> fd = os.open("/dev/null", os.O_RDWR)
> os.dup2(fd, 0)
> os.dup2(fd, 1)
> os.dup2(fd, 2)
> if fd > 2:
> os.close(fd)
> # do stuff
>
> Although bear in mind it's pretty UNIX-y.

IIRC you have to fork a second time after you have changed the working
dir and created a new session group.

Christian

Jon Ribbens

2/4/2008 2:58:00 PM

0

On 2008-02-04, Christian Heimes <lists@cheimes.de> wrote:
>> Although bear in mind it's pretty UNIX-y.
>
> IIRC you have to fork a second time after you have changed the working
> dir and created a new session group.

Why? I don't think you do.
Neither does BSD daemon.c or glibc daemon.c

Bernard

2/4/2008 2:59:00 PM

0

On 3 fév, 21:52, Gilles Ganault <nos...@nospam.com> wrote:
> Hello
>
> I need to launch a Python script, and fork it so that the calling
> script can resume with the next step will the Python script keeps
> running.
>
> I tried those two, but they don't work, as the calling script is stuck
> until the Python script ends:
>
> sys.stdout = open(os.devnull, 'w')
>
> =====
> #if os.fork():
> pid = os.fork()
> if pid > 0:
> sys.exit(0)
> =====
>
> Should I use another library to do this?
>
> Thank you.

this works out for me:

def tryToFork(cbk, fork=True):
'''
If possible, start the process as a daemon under linux
otherwise start it normally under Windows

the 'fork' flag may deactivate the forking if it is set to False
'''

#UNIX/LINUX: FORK
if fork:
try:
#Fork and commit suicide
if os.fork():
sys.exit(0)

#What to do in parent process
else:
os.setsid()
sys.stdin = open('/dev/null')
sys.stdout = open('/dev/null', 'w')
sys.stderr = open('/dev/null', 'w')
cbk()

#WINDOWS: JUST RUN
except AttributeError:
cbk()

#PLAIN, NORMAL RUN
else:
cbk()

def whateverFunctionToFork():
pass
tryToFork(whateverFunctionToFork, True)

Jon Ribbens

2/4/2008 3:04:00 PM

0

On 2008-02-04, Bernard <bernard.chhun@gmail.com> wrote:
> #Fork and commit suicide
> if os.fork():
> sys.exit(0)

I'm pretty sure that should be os._exit(0)

> #What to do in parent process

This is now the child process.

> sys.stdin = open('/dev/null')
> sys.stdout = open('/dev/null', 'w')
> sys.stderr = open('/dev/null', 'w')

I think that's changing Python's idea of stdin etc but not the
operating system's idea of them. You won't be closing the original
file descriptors, and if you run any subprocesses they will end up
with the original stdin/out/err. Unless sys.stdin is more magic
than I'm aware of.

Christian Heimes

2/4/2008 3:29:00 PM

0

Jon Ribbens wrote:
> I think that's changing Python's idea of stdin etc but not the
> operating system's idea of them. You won't be closing the original
> file descriptors, and if you run any subprocesses they will end up
> with the original stdin/out/err. Unless sys.stdin is more magic
> than I'm aware of.

Jon is correct here. You must close or redirect the underlying C file
descriptor. Python's sys.std streams don't magically do this for you
because Python keeps a backup of the standard streams for internal
purpose in sys.__std*__. os.dup2 is the best solution.

Christian

Christian Heimes

2/4/2008 3:32:00 PM

0

Jon Ribbens wrote:
> Why? I don't think you do.
> Neither does BSD daemon.c or glibc daemon.c

The problem is well documented at
http://aspn.activestate.com/ASPN/Cookbook/Python/Re...

"""
The second fork _is_ necessary, Jonathan Bartlett, 2003/10/31
The first fork accomplishes two things - allow the shell to return, and
allow you to do a setsid().

The setsid() removes yourself from your controlling terminal. You see,
before, you were still listed as a job of your previous process, and
therefore the user might accidentally send you a signal. setsid() gives
you a new session, and removes the existing controlling terminal.

The problem is, you are now a session leader. As a session leader, if
you open a file descriptor that is a terminal, it will become your
controlling terminal (oops!). Therefore, the second fork makes you NOT
be a session leader. Only session leaders can acquire a controlling
terminal, so you can open up any file you wish without worrying that it
will make you a controlling terminal.

So - first fork - allow shell to return, and permit you to call setsid()

Second fork - prevent you from accidentally reacquiring a controlling
terminal.
"""

Rolf van de Krol

2/4/2008 3:40:00 PM

0

To create a deamon, you indeed need to fork two times. For more
information and a working example see:
http://aspn.activestate.com/ASPN/Cookbook/Python/Rec... . I'm
quite sure this works, because I used it several times to create a deamon.


Jon Ribbens wrote:
> On 2008-02-04, Christian Heimes <lists@cheimes.de> wrote:
>
>>> Although bear in mind it's pretty UNIX-y.
>>>
>> IIRC you have to fork a second time after you have changed the working
>> dir and created a new session group.
>>
>
> Why? I don't think you do.
> Neither does BSD daemon.c or glibc daemon.c
>

Jon Ribbens

2/4/2008 4:46:00 PM

0

On 2008-02-04, Rolf van de Krol <python@rolfvandekrol.nl> wrote:
> To create a deamon, you indeed need to fork two times. For more
> information and a working example see:
> http://aspn.activestate.com/ASPN/Cookbook/Python/Rec... . I'm
> quite sure this works, because I used it several times to create a deamon.

That doesn't mean it works. That just means it hasn't failed while
you were watching.

(Not that I am saying it's necessarily wrong, I'm just saying that
"it worked when I tried it" is a very bad way of deciding if something
is correct code.)