views:

627

answers:

6

Is it possible to run a Python script as a background service on a webserver? I want to do this for socket communication.

A: 

Assuming this is for Windows, see this recipe based on srvany

mjv
+4  A: 

You might want to check out Twisted.

Fragsworth
I checked it out, and its quite confusing to grasp. So Twisted is a Python library, which keeps a python script running forever for whatever communication task? (eg. Sockets)
Jenko
Twisted is a python library for writing servers.Once you write a server in twisted, you can use 'twistd -y server.py' to run it as a daemon
Nathan
A: 

If you are talking about linux, it is as easy as doing something like ./myscript.py &

Unknown
Andre Miller
What Andre said. I neglected to mention nohup because I usually just run screen and detach, so there's no need for me to do that. These downvoters are vicious.
Unknown
But even if you're running screen, you haven't created a true daemon, it's still a child of your screen session. nohup isn't the best solution either, but it's a quick way to run a once off daemon.
JimB
http://en.wikipedia.org/wiki/Daemon_%28computer_software%29 "a daemon is a computer program that runs in the background". I think this qualifies.
Unknown
And if you keep reading: "In a Unix environment, the parent process of a daemon is often (but not always) the init process (PID=1). Processes usually become daemons by forking a child process and then having their parent process immediately exit, thus causing init to adopt the child process. This is a somewhat simplified view of the process as other operations are generally performed, such as disassociating the daemon process from any controlling tty. Convenience routines such as daemon(3) exist in some UNIX systems for that purpose" http://en.wikipedia.org/wiki/Daemon_%28computer_software%29
JimB
... ... starting from screen doesn't give the process over to init, and starting from nohup doesn't create the process as a process group leader. http://en.wikipedia.org/wiki/Daemon_%28computer_software%29#Types_of_daemons
JimB
JimB
+2  A: 

on XP and later you can use the sc.exe program to use any .exe as service:

>sc create
Creates a service entry in the registry and Service Database.
SYNTAX:
sc create [service name] [binPath= ] <option1> <option2>...
CREATE OPTIONS:
NOTE: The option name includes the equal sign.
 type= <own|share|interact|kernel|filesys|rec>
       (default = own)
 start= <boot|system|auto|demand|disabled>
       (default = demand)
 error= <normal|severe|critical|ignore>
       (default = normal)
 binPath= <BinaryPathName>
 group= <LoadOrderGroup>
 tag= <yes|no>
 depend= <Dependencies(separated by / (forward slash))>
 obj= <AccountName|ObjectName>
       (default = LocalSystem)
 DisplayName= <display name>
 password= <password>

You can start your pythonscript by starting the python interpreter with your script as argument:

python.exe myscript.py
Peter Parker
I have a .py Python script. Where's the EXE?
Jenko
Try py2exe http://www.py2exe.org
Yancy
you just can start python interpreter with your script as argument: python.exe myscript.py
Peter Parker
I'm pretty sure you can't just use sc.exe to make any process a service. It must implement the Windows Service interface, such as that provided by the win32serviceutil module (part of pywin32).
Jason R. Coombs
+3  A: 

You can make it a daemon. There is a PEP for a more complete solution, but I have found that this works well.

import os, sys

def become_daemon(our_home_dir='.', out_log='/dev/null', err_log='/dev/null', pidfile='/var/tmp/daemon.pid'):
    """ Make the current process a daemon.  """

    try:
        # First fork
        try:
            if os.fork() > 0:
                sys.exit(0)
        except OSError, e:
            sys.stderr.write('fork #1 failed" (%d) %s\n' % (e.errno, e.strerror))
            sys.exit(1)

        os.setsid()
        os.chdir(our_home_dir)
        os.umask(0)

        # Second fork
        try:
            pid = os.fork()
            if pid > 0:
                # You must write the pid file here.  After the exit()
                # the pid variable is gone.
                fpid = open(pidfile, 'wb')
                fpid.write(str(pid))
                fpid.close()
                sys.exit(0)
        except OSError, e:
            sys.stderr.write('fork #2 failed" (%d) %s\n' % (e.errno, e.strerror))
            sys.exit(1)

        si = open('/dev/null', 'r')
        so = open(out_log, 'a+', 0)
        se = open(err_log, 'a+', 0)
        os.dup2(si.fileno(), sys.stdin.fileno())
        os.dup2(so.fileno(), sys.stdout.fileno())
        os.dup2(se.fileno(), sys.stderr.fileno())
    except Exception, e:
        sys.stderr.write(str(e))
Robert
In the code snippet above, I can see at least one problem: sniffing daemon presence isn't done before attempting to launch a fresh instance.
jldupont
sniffing? Do you mean checking if the daemon is already running? if so, this is done in a different procedure before call the above.
Robert
+1  A: 

There is the very helpful Pypi package which is the basis for my daemons written in Python.

jldupont