I have a simple web.py program to load data. In the server I don't want to install apache or any webserver.
I try to put it as a background service with http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/
And subclassing:
(from http://www.jejik.com/files/examples/daemon.py)
class Daemon:
def start(self):
"""
Start the daemon
"""
... PID CHECKS....
# Start the daemon
self.daemonize()
self.run()
#My code
class WebService(Daemon):
def run(self):
app.run()
if __name__ == "__main__":
if DEBUG:
app.run()
else:
service = WebService(os.path.join(DIR_ACTUAL,'ElAdministrador.pid'))
if len(sys.argv) == 2:
if 'start' == sys.argv[1]:
service.start()
elif 'stop' == sys.argv[1]:
service.stop()
elif 'restart' == sys.argv[1]:
service.restart()
else:
print "Unknown command"
sys.exit(2)
sys.exit(0)
else:
print "usage: %s start|stop|restart" % sys.argv[0]
sys.exit(2)
However, the web.py software not load (ie: The service no listen)
If I call it directly (ie: No using the daemon code) work fine.
I finally find the problem.
Web.py accept from command-line the optional port number:
python code.py 80
And the script also take input from the command-line:
python WebServer start
then web.py try to use "start" as port number and fail. I don't see the error because was in the bacground.
I fix this with a mini-hack:
if __name__ == "__main__":
if DEBUG:
app.run()
else:
service = WebService(os.path.join(DIR_ACTUAL,'ElAdministrador.pid'))
if len(sys.argv) == 2:
if 'start' == sys.argv[1]:
sys.argv[1] = '8080'
service.start()
you can start the web.py by using this command
/usr/bin/python index.py > log.txt 2>&1 &
I don't think you're telling the daemon to run. You need to instantiate a MyDaemon object and call o.run(). It looks like WebService only starts and stops the service interface to your web app, not the actual web app itself.
Instead of overwrite the second argument like you wrote here:
if __name__ == "__main__":
if DEBUG:
app.run()
else:
service = WebService(os.path.join(DIR_ACTUAL,'ElAdministrador.pid'))
if len(sys.argv) == 2:
if 'start' == sys.argv[1]:
sys.argv[1] = '8080'
service.start()
you could just delete the second argument on 'start|restart', like this:
if __name__ == "__main__":
if DEBUG:
app.run()
else:
service = WebService(os.path.join(DIR_ACTUAL,'ElAdministrador.pid'))
if len(sys.argv) == 2:
if 'start' == sys.argv[1]:
delete del sys.argv[1:2]
service.start()
In this way, the webpy will receive all the arguments you passed from command line except the daemon controller. Then you can run simply:
python WebServer start 8080
Related
tl,dr: How can I programmably execute a python module (not function) as a separate process from a different python module?
On my development laptop, I have a 'server' module containing a bottle server. In this module, the name==main clause starts the bottle server.
#bt_app.post("/")
def server_post():
<< Generate response to 'http://server.com/' >>
if __name__ == '__main__':
serve(bt_app, port=localhost:8080)
I also have a 'test_server' module containing pytests. In this module, the name==main clause runs pytest and displays the results.
def test_something():
_rtn = some_server_function()
assert _rtn == desired
if __name__ == '__main__':
_rtn = pytest.main([__file__])
print("Pytest returned: ", _rtn)
Currently, I manually run the server module (starting the web server on localhost), then I manually start the pytest module which issues html requests to the running server module and checks the responses.
Sometimes I forget to start the server module. No big deal but annoying. So I'd like to know if I can programmatically start the server module as a separate process from the pytest module (just as I'm doing manually now) so I don't forget to start it manually.
Thanks
There is my test cases dir tree:
test
├── server.py
└── test_server.py
server.py start a web server with flask.
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello, World!'
if __name__ == '__main__':
app.run()
test_server.py make request to test.
import sys
import requests
import subprocess
import time
p = None # server process
def start_server():
global p
sys.path.append('/tmp/test')
# here you may want to do some check.
# whether the server is already started, then pass this fucntion
kwargs = {} # here u can pass other args needed
p = subprocess.Popen(['python','server.py'], **kwargs)
def test_function():
response = requests.get('http://localhost:5000/')
print('This is response body: ', response.text)
if __name__ == '__main__':
start_server()
time.sleep(3) # waiting server started
test_function()
p.kill()
Then you can do python test_server to start the server and do test cases.
PS: Popen() needs python3.5+. if older version, use run instead
import logging
import threading
import time
def thread_function(name):
logging.info("Thread %s: starting", name)
time.sleep(2)
logging.info("Thread %s: finishing", name)
if __name__ == "__main__":
format = "%(asctime)s: %(message)s"
logging.basicConfig(format=format, level=logging.INFO,
datefmt="%H:%M:%S")
threads = list()
for index in range(3):
logging.info("Main : create and start thread %d.", index)
x = threading.Thread(target=thread_function, args=(index,))
threads.append(x)
x.start()
for index, thread in enumerate(threads):
logging.info("Main : before joining thread %d.", index)
thread.join()
logging.info("Main : thread %d done", index)
With threading you can run multiple processes at once!
Wim baasically answered this question. I looked into the subprocess module. While reading up on it, I stumbled on the os.system function.
In short, subprocess is a highly flexible and functional program for running a program. os.system, on the other hand, is much simpler, with far fewer functions.
Just running a python module is simple, so I settled on os.system.
import os
server_path = "python -m ../src/server.py"
os.system(server_path)
Wim, thanks for the pointer. Had it been a full fledged answer I would have upvoted it. Redo it as a full fledged answer and I'll do so.
Async to the rescue.
import gevent
from gevent import monkey, spawn
monkey.patch_all()
from gevent.pywsgi import WSGIServer
#bt_app.post("/")
def server_post():
<< Generate response to 'http://server.com/' >>
def test_something():
_rtn = some_server_function()
assert _rtn == desired
print("Pytest returned: ",_rtn)
sleep(0)
if __name__ == '__main__':
spawn(test_something) #runs async
server = WSGIServer(("0.0.0.0", 8080, bt_app)
server.serve_forever()
I created a Windows Service with python. It works well when I run it with debug mode, but when I start the service it doesn't work. This is the sample of my script:
def run(param):
subprocess.Popen(["C:\\SER\\txt_write.pyw",param], shell=True)
#txt_write is a simple script: put the parameter into b.txt
def add_param():
x="123456"
run(x)
class PythonCornerExample(SMWinservice):
_svc_name_ = "name"
_svc_display_name_ = "name disp"
_svc_description_ = "desc"
def start(self):
self.isrunning = True
def stop(self):
self.isrunning = False
def main(self):
i=0
while self.isrunning:
add_param()
f= open("C:\\SER\\a.txt","a+")
f.write("xyz")
f.close()
time.sleep(25)
if __name__ == '__main__':
PythonCornerExample.parse_command_line()
So, when I run this script in debug mode it put "xyz" text into a.txt, and calls another python script, that put the parameter (123456) into b.txt. This is how I want it to works.
My problem is, installed as Windows Service the a.txt works, but b.txt doesn't.
What is wrong with my script? Why is it OK in debug mode, and why is it wrong as Services?
change last 2 lines with bellow code:
import servicemanager, sys
if __name__ == '__main__':
if len(sys.argv) == 1:
servicemanager.Initialize()
servicemanager.PrepareToHostSingle(PythonCornerExample)
servicemanager.StartServiceCtrlDispatcher()
else:
PythonCornerExample.parse_command_line()
The arguments passed by the service start are in the args parameter of the constructor method of your class.
class AppServerSvc (win32serviceutil.ServiceFramework):
def __init__(self, **args**):
You want them in sys.argv, where you'd get them if the parameters were coming from a command line.
So I simply did this.
sys.argv = args
And now I'm parsing my service parameters as if it came from the command line.
:)
I've found 'daemon.py' script by Sander Marechal and I want to use it to execute my simply test script which prints text. When I execute script without 'execfile()' it creates daemon-example.pid and daemon works but when I add 'execfile()' it doesn't work.
here is code:
#!/usr/bin/env python
import sys
from daemon import Daemon
class MyDaemon(Daemon):
def run(self):
while True:
execfile("text.py")
time.sleep(1)
if __name__ == "__main__":
daemon = MyDaemon('/tmp/daemon-example.pid')
if len(sys.argv) == 2:
if 'start' == sys.argv[1]:
daemon.start()
elif 'stop' == sys.argv[1]:
daemon.stop()
elif 'restart' == sys.argv[1]:
daemon.restart()
else:
print "Unknown command"
sys.exit(2)
sys.exit(0)
else:
print "usage: %s start|stop|restart" % sys.argv[0]
sys.exit(2)
I am building a simple pyhon daemon based on Sander Marechal's code. Daemon's whole purpose is to run a php file every second (php file loops through database checking values and updating database). Problem arises on the section
subprocess.call(['php','test.php'])
I can run "php test.php" on shell and it does what it is suppose to do but when it is called periodically from the daemon it doesn't seem to be executed. I also know daemon works on the background via checking running process ps aux | grep "daemon-example" also i included a do_something function which records every time function executed and appends time to a text file.
#!/usr/bin/env python
import sys, time,subprocess
from daemon import Daemon
def runphp():
#subprocess.call(['php ~/pydaemon/test.php'], shell=True)
subprocess.call(['python', 'test.py'])
def do_something():
with open("/tmp/current_time.txt",'a') as f:
f.write("The time is now\n" + time.ctime())
class MyDaemon(Daemon):
def run(self):
while True:
time.sleep(1)
do_something()
subprocess.call(['php','test.php'])
#runphp()
if __name__ == "__main__":
daemon = MyDaemon('/tmp/daemon-example.pid')
if len(sys.argv) == 2:
if 'start' == sys.argv[1]:
daemon.start()
elif 'stop' == sys.argv[1]:
daemon.stop()
elif 'restart' == sys.argv[1]:
daemon.restart()
else:
print "Unknown command"
sys.exit(2)
sys.exit(0)
else:
print "usage: %s start|stop|restart" % sys.argv[0]
sys.exit(2)
The script you are trying to run is not executed because the working directory is the root directory ('/') and that's because of this piece of code:
# decouple from parent environment
os.chdir("/")
So actually your code tries to execute: python /test.py(which does not exist) and not 'your_current_directory/test.py'.
To fix it either remove os.chdir("/"), or provide the full path to the file like so:
subprocess.call(['python','my_full_path_to_working_directory/test.py'])
I am trying to write dbus server where I want to run some external shell program (grep here) to do the job.
when I do:
prompt$ server.py
then:
prompt$ client.py # works fine, ie. runs grep command in child process.
prompt$ client.py # ..., but second invocation produces following error message:
DBusException: org.freedesktop.DBus.Error.ServiceUnknown: The name org.example.ExampleService was not provided by any .service files
I am stuck. Are You able to help me?
here is server.py (client.py thereafter):
import gtk, glib
import os
import dbus
import dbus.service
import dbus.mainloop.glib
import subprocess
messages_queue=list()
grep_pid=0
def queue_msg(message):
global messages_queue
messages_queue.append(message)
return
def dequeue_msg():
global messages_queue,grep_pid
if grep_pid != 0:
try:
pid=os.waitpid(grep_pid,os.P_NOWAIT)
except:
return True
if pid[0] == 0:
return True
grep_pid=0
if len(messages_queue) == 0:
return True
else:
tekst=messages_queue.pop(0)
cmd="grep 'pp'"
print cmd
#works fine, when I do return here
#return True
grep_pid=os.fork()
if grep_pid != 0:
return True
os.setpgid(0,0)
pop=subprocess.Popen(cmd,shell=True,stdin=subprocess.PIPE)
pop.stdin.write(tekst)
pop.stdin.close()
pop.wait()
exit(0)
class DemoException(dbus.DBusException):
_dbus_error_name = 'org.example.Exception'
class MyServer(dbus.service.Object):
#dbus.service.method("org.example.ExampleInterface",
in_signature='', out_signature='')
def QueueMsg(self):
queue_msg("ppppp")
#dbus.service.method("org.example.ExampleInterface",
in_signature='', out_signature='')
def Exit(self):
mainloop.quit()
from dbus.mainloop.glib import threads_init
if __name__ == '__main__':
glib.threads_init()
threads_init()
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
session_bus = dbus.SessionBus()
name = dbus.service.BusName("org.example.ExampleService", session_bus)
object = MyServer(session_bus, '/My')
glib.timeout_add_seconds(1, dequeue_msg)
mainloop = glib.MainLoop()
print "Running example service."
mainloop.run()
now client.py:
import sys
from traceback import print_exc
import dbus
def main():
bus = dbus.SessionBus()
try:
remote_object = bus.get_object("org.example.ExampleService",
"/My")
except dbus.DBusException:
print_exc()
sys.exit(1)
iface = dbus.Interface(remote_object, "org.example.ExampleInterface")
iface.QueueMsg()
if sys.argv[1:] == ['--exit-service']:
iface.Exit()
if __name__ == '__main__':
main()
You usually get this error message when you try to access a service that is no longer available. Check if your server is still running.
You can use d-feet to debug your dbus connections.
The error message about the missing .service file means that you need to create a service file in dbus-1/services.
For example:
# /usr/local/share/dbus-1/services/org.example.ExampleService.service
[D-BUS Service]
Name=org.example.ExampleService
Exec=/home/user1401567/service.py
A lot of tutorials don't include this detail (maybe .service files didn't use to be required?) But, at least on Ubuntu 12.04, dbus services can't be connected to without it.