Monday, September 12, 2005

Running a Python script as a Windows service

This is a message I posted to comp.lang.py regarding ways to run a regular Python script as a Windows service.

I will assume you want to turn a script called myscript.py into a service.

1. Install Win2K Resource Kit (or copy the 2 binaries instsrv.exe and srvany.exe).

2. Run instsrv to install srvany.exe as a service with the name myscript:
C:\Program Files\Resource Kit\instsrv myscript "C:\Program Files\Resource Kit\srvany.exe"

3. Go to Computer Management->Services and make sure myscript is listed as a service. Also make sure the Startup Type is Automatic.

4. Create a myscript.bat file with the following contents in e.g. C:\pyscripts:

C:\Python23\python C:\pyscripts\myscript.py

(replace Python23 with your Python version)

5. Create new registry entries for the new service.
  • run regedt32 and go to the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\myscript entry
  • add new key (Edit->Add Key) called Parameters
  • add new entry for Parameters key (Edit->Add Value) to set the Application name
    • Name should be Application
    • Type should be REG_SZ
    • Value should be path to myscript.bat, i.e. C:\pyscripts\myscript.bat
  • add new entry for Parameters key (Edit->Add Value) to set the working directory
    • Name should be AppDir
    • Type should be REG_SZ
    • Value should be path to pyscripts directory, i.e. C:\pyscripts
6. Test starting and stopping the myscript service in Computer
Management->Services.

24 comments:

Anonymous said...

awesome :-D

Richard Quadling said...

Hi.

Just found your little blog about running Python as a service.

I've not got the NTLM APS server running! Excellent.

Some slight differences which remove the need for the batch file ...

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NTLM APS\Parameters]
"Application"="C:\\Python\\pythonw.exe"
"AppDirectory"="C:\\APS"
"AppParameters"="C:\\APS\\Main.pyc"

On my version of srvany.exe, I need to use AppDirectory.

And by using PythonW as my application, I don't get anything on screen. I used to have C:\APS\main.pyc in my startup folder (I've compiled the .py files and set the pyc handler to be C:\python\pythonw.exe)

Anyway, EXCELLENT blog. VERY useful. THANK YOU!!!!

Regards,

Richard Quadling.

Anonymous said...

Great post! Thanks for the help!

I too was attempting to get the NTLM APS (aps098) proxy authentication server working as a service. I found both the first post and Richard's very helpful. I did have to change some things that Richard posted.

I deleted the "AppParameters" key and changed "Application" to "C:\Python\python main.py". Also note that I did not use the double \ (ie. C:\\Python). It's working great! Thanks

-G. Strike

D. Adams said...

Problem - Visual Basic using Python math

Hi David,

visited your site in the past. Wondering if you might either know how to solve the following, or perhaps point me to someone else. Know any good Python forums you would recommend?

I've a background in Visual Basic, and am using an old version, 4.0, it compiles to a smaller executable which I prefer. I find myself in an odd situation, needing a very simple yet powerful capability of Python for a VB app
Im working on.

Simply, a large 300 digit number is divided by a smaller number ranging from 1 to 3 digits. I.e;

This large 300 digit number is generated as a string from the VB app, and I want to input this somehow
from the VB app directly to Python for simple math operations.

Where; x = 300 digit number, y = divisor ( say '37')


x / 37

I want to divide x by y but I want the remainder of this division to at least 3 or 4 decimal places, so my Python script at the command line;

x %y /y. = z

So now I want to take the resultant, the full number plus its remainder, and I want to round this number up
to the next highest number and divide it by the same constant;

z rounded up to next highest number (never the lowest)

so

z /y = z Long

Remove the 'L' at the end, round up the last digit of z = Z

Then;

Z %y /y. = a

Then I want the last five digits of z (not Z) and a truncated at the end, so the last digit before
the decimal point and the four digits past the decimal point printed to a text file.

I want to be able to open the text file with the VB app and use this data as inputs.
==========

Ok, so here is my dilemma, I know VERY litle about Python and a fair bit about VB.

Ideally, I'd love to be able to simply have some extremely small executable that just accepts inputs
does the calculations above and then spits out the outputs. If it were possible to write some
simple lines of math code in Python and then compile these scripts in Python to a Windows
compatible executable,that would be fantastic.

If I could simply have my VB app, 'call' the name of the tiny Python executable, and then the Python executable
just automatically looked for a named text file (created by the VB app) and extracted the 300 digit number from this, then performed the calcs, then spit this data out as a new text file name it created, which I could then use the VB app to open and read from, THAT would be ideal.

However, I don't know if Python can compile scripts to an exe? If it can how could I find out how to do this?

If it doesn't, how could I get VB to directly pass commands to the Python command line and then automatically
extract the outputs? Shelling out from VB to Python would be tough to the command line I think, since the Python command line uses the 'Edit / Mark, Paste' approach to inserting, copy inputs, outputs and this would be virtually untenable, as far as I can tell to automate in a VB shell out routine.

So basically, how the heck can I access Pythons ability to perform simple calculations on very large numbers, easily, from within VB 4.0 ? There must be a way, it seems like such a simple think to do, especially since the actual math operations are so simple, straight forward, and would never change.....

Any ideas?

Anonymous said...

Problem - Visual Basic using Python math


visited your site in the past. Wondering if you might either know how to solve the following, or perhaps point me to someone else. Know any good Python forums you would recommend?

I've a background in Visual Basic, and am using an old version, 4.0, it compiles to a smaller executable which I prefer. I find myself in an odd situation, needing a very simple yet powerful capability of Python for a VB app
Im working on.

Simply, a large 300 digit number is divided by a smaller number ranging from 1 to 3 digits. I.e;

This large 300 digit number is generated as a string from the VB app, and I want to input this somehow
from the VB app directly to Python for simple math operations.

Where; x = 300 digit number, y = divisor ( say '37')


x / 37

I want to divide x by y but I want the remainder of this division to at least 3 or 4 decimal places, so my Python script at the command line;

x %y /y. = z

So now I want to take the resultant, the full number plus its remainder, and I want to round this number up
to the next highest number and divide it by the same constant;

z rounded up to next highest number (never the lowest)

so

z /y = z Long

Remove the 'L' at the end, round up the last digit of z = Z

Then;

Z %y /y. = a

Then I want the last five digits of z (not Z) and a truncated at the end, so the last digit before
the decimal point and the four digits past the decimal point printed to a text file.

I want to be able to open the text file with the VB app and use this data as inputs.
==========

Ok, so here is my dilemma, I know VERY litle about Python and a fair bit about VB.

Ideally, I'd love to be able to simply have some extremely small executable that just accepts inputs
does the calculations above and then spits out the outputs. If it were possible to write some
simple lines of math code in Python and then compile these scripts in Python to a Windows
compatible executable,that would be fantastic.

If I could simply have my VB app, 'call' the name of the tiny Python executable, and then the Python executable
just automatically looked for a named text file (created by the VB app) and extracted the 300 digit number from this, then performed the calcs, then spit this data out as a new text file name it created, which I could then use the VB app to open and read from, THAT would be ideal.

However, I don't know if Python can compile scripts to an exe? If it can how could I find out how to do this?

If it doesn't, how could I get VB to directly pass commands to the Python command line and then automatically
extract the outputs? Shelling out from VB to Python would be tough to the command line I think, since the Python command line uses the 'Edit / Mark, Paste' approach to inserting, copy inputs, outputs and this would be virtually untenable, as far as I can tell to automate in a VB shell out routine.

So basically, how the heck can I access Pythons ability to perform simple calculations on very large numbers, easily, from within VB 4.0 ? There must be a way, it seems like such a simple think to do, especially since the actual math operations are so simple, straight forward, and would never change.....

Any ideas?

Grig Gheorghiu said...

For converting Python scripts into executables, check out py2exe.

But this is not strictly necessary for your problem, because you can simply invoke "python your_script" from VB.

After installing Python on your system (I recommend Active State's ActivePython distro), you just need to write a python script that reads from a known file, does the calculation, then writes to a file. Let's call it do_calc.py.

You then call that script via the Shell command in VB. Something like

Shell("python C:\whatever\do_calc.py")

For a very good python forum, see comp.lang.python.

Hope this helps.

Grig

Matthew said...

When running a service there are a couple of gotchas that can catch you out.

Firstly, the service runs in a blank environment with none of the environment variables set that you might have had in your test environment. Nor, crucialy, will it have any drive mappings. Therefore your script cannot be directly run off a network drive. Instead, if mappings are required, the script run by SrvAny should be local to the machine and should itself map drives and configure the environment as required for the main program.

Secondly, if you use a bat file to start a python script, especially with pythonw, it may not stop when asked to do so from the service manager. To achieve this I've written a C# service which starts the bat file, and stops the pythonw process using 'taskkill /F /IM pythonw.exe'. It's a little heavy duty, and could be dangerous on some machines, but it works for my case.

Deepak Sakpal said...

How can I run a Python script as a Windows service in Windows 2003 Server?

Anonymous said...

This is an excellent and very very very useful information. Thanks to Grip who has posted this and also the website supporting such nice information

Anonymous said...

I use FireDaemon Lite ver 1.6 GA. It will run any script/executable as a service. That version is free. Here is one link http://www.tsfclan.be/index.php?page=6

Tzury said...

On Windows 2003 skip the AppDir!

Catherine said...

This is great, Grig! I Googled up half the web, trying to find a working example, before I finally found yours. Thanks!

Grig Gheorghiu said...

Catherine -- glad you found it useful!

Grig

Steven said...

I’m trying to find out about Unified Communication for a project but there doesn’t seem to be much information available. Is it the same as VoIP, and if not how is it different?

Richard Lewis said...

Any ideas how to set the working directory? (On Windows Server 2003 if it makes any difference.)

I've tried changing the name of the AppDir value to AppDirectory. I've also tried adding a cd "C:\..." as the first command of the batch file. Neither seems to work.

My script relies on being able to load files using relative paths. At the moment it reports errors because it can't find the files.

Thanks for any suggestions.

Grig Gheorghiu said...

Richard -- I would have thought adding a 'cd C:\your_path\' at the start of the bat file would help....But apparently not.

Not sure what to suggest, except modifying your script to read in absolute file names as opposed to relative ones.

Grig

Anonymous said...

Awesome. And thanks to Richard Quadling, I got it working fully.

I'd post with name, but I'm at Ubisoft and our Nazi firewall doesn't allow Google logins. :(

Ray said...

Excellent article, and also thanks to Richard Quadling for showing how to do this without a batch file.

Strangely, with the batch file on my Windows 2003 Server machine, stopping the service seemed to create a zombie python.exe process, which was causing little annoyances.

Modifying the registry to allow for pythonw.exe fixed the problem.

David Jackson said...

I have actually used srvany.exe to create a Windows service (XP) only to realize a few days later that the service has stopped. the same script will run without any error for days from the console ; problem is with srvany.exe. what other methods of creating a windows service for python script are there?

Anonymous said...

I've compiled a python script with py2exe and I originally try to use srvany to create a service on windows 2008. I discoved srvany is not supported on this OS so I used sc.exe but when starting the service it alsways failing. is one of you has done that

Rob M said...

Using this on a solar house that's in the 2009 solar decathlon.
Thanks for posting, wasn't sure how I was gonna have my little python script (which keeps growing in what it needs to handle) be reliable.

PC Repair said...

Thanks a million for this post. I just started working on a project and was looking for ways to run some of my Python as a service on Windows.

Awesome tip - thanks for sharing

Mintaka said...

It look little strange. To run Python script as MS Windows service can be helpfull book:

Python Programming on Win32, Mark Hammond, Chapter 18. Windows NT Services

Old, but still useable.

Alex Garel said...

Grig you really made my Day !

@Matthew your comment was also really helpful as I first was on a network drive…

http://www.iopus.com/guides/srvany.htm also helped me for the "Interact with desktop" box.