3
\$\begingroup\$

I am fairly new to Python and programming in general so I hope the code in this post is not too messy. I have the following code which I use for taking images from an IP security camera:

def Camera(timecount, cam_name, stream_url, username, password, work_dir, x):
    x = x
    work_dir = work_dir
    h = httplib.HTTP(stream_url)
    h.putrequest('GET', '/videostream.cgi')
    h.putheader('Authorization', 'Basic %s' % base64.encodestring('%s:%s' % (username, password))[:-1])
    h.endheaders()
    errcode, errmsg, headers = h.getreply()
    stream_file = h.getfile()
    start = time.time()
    end = start + timecount
    while time.time() <= end:
        if not os.path.isfile("/tmp/sec.lck"):
            sys.exit()
        x += 1
        now = datetime.datetime.now()
        dte = str(now.day) + "-" + str(now.month) + "-" + str(now.year)
        dte1 = str(now.hour) + ":" + str(now.minute) + ":" + str(now.second) + "." + str(now.microsecond)
        cname = "Cam#: " + cam_name
        dnow = """Date: %s """ % dte
        dnow1 = """Time: %s""" % dte1
        source_name = stream_file.readline()    # '--ipcamera'
        content_type = stream_file.readline()    # 'Content-Type: image/jpeg'
        content_length = stream_file.readline()   # 'Content-Length: 19565'
        b1 = b2 = b''
        while True:
            b1 = stream_file.read(1)
            while b1 != chr(0xff):
                b1 = stream_file.read(1)
            b2 = stream_file.read(1)
            if b2 == chr(0xd8):
                break
            # pull the jpeg data
            framesize = int(content_length[16:])
            jpeg_stripped = b''.join((b1, b2, stream_file.read(framesize - 2)))
            # throw away the remaining stream data. Sorry I have no idea what it is
            junk_for_now = stream_file.readline()
            image_as_file = io.BytesIO(jpeg_stripped)
            image_as_pil = Image.open(image_as_file)
            draw = ImageDraw.Draw(image_as_pil)
            draw.text((0, 0), cname, fill="white")
            draw.text((0, 10), dnow, fill="white")
            draw.text((0, 20), dnow1, fill="white")
            img_name = cam_name + "-" + tod + "-" + str('%010d' % x) + ".jpg"
            img_path = os.path.join(work_dir, img_name)
            image_as_pil.save(img_path)

With it I run the code twice (2 separate threads) with the following code:

def main():
    parser = SafeConfigParser()

    # Open the file with the settings
    with codecs.open('Settings/settings.ini', 'r', encoding='utf-8') as f:
        parser.readfp(f)

    procs = list()
    for cam_name in parser.sections():
        cam_name = cam_name
        stream_url = parser.get(cam_name, 'stream_url')
        username = parser.get(cam_name, 'username')
        password = parser.get(cam_name, 'password')
        work_dir = parser.get(cam_name, 'work_dir') + tod + "/"

        x = sum(1 for f in os.listdir(work_dir) if f.startswith(cam_name) and os.path.isfile(os.path.join(work_dir, f)))
        for i in range(1):
                q = multiprocessing.Process(target=Camera, args=(timecount, cam_name, stream_url, username, password, work_dir, x,))
                procs.append(q)
                q.start()

    for p in procs:
        p.join()

UPDATE:

I am currently using the following to start and stop the script:

I added this just after the (while time.time() <= end:) in the camera thread / function:

if not os.path.isfile("/tmp/sec.lck"):
    sys.exit()

and changed the "main" function from just main() to the following:

if __name__ == "__main__":
    if len(sys.argv) == 2:
        if 'start' == sys.argv[1]:
            open('/tmp/sec.lck', 'w').close()
            main()
        elif 'stop' == sys.argv[1]:
            os.remove("/tmp/sec.lck")
            print "Stopping SecCam"
        elif 'restart' == sys.argv[1]:
            os.remove("/tmp/sec.lck")
            time.sleep(1)
            open('/tmp/sec.lck', 'w').close()
            main()
        else:
            print "Unknown command"
            sys.exit(2)
            sys.exit(0)
        else:
            print "usage: %s start|stop|restart" % sys.argv[0]
            sys.exit(2)

This appears to be working it checks for the sec.lck file if it is not there it exits.

Can this program be improved further?

\$\endgroup\$
  • \$\begingroup\$ If you do not have the daemon code working then it is not yet ready for review. Other parts of your code may in fact be working, but, at this point, the overall question is off-topic because it is asking for help to write new code/fix broken code. When your code works as designed, bring it back here for review... Please see our help center for more details. \$\endgroup\$ – rolfl Apr 20 '14 at 18:51
6
\$\begingroup\$

These statements are pointless, you can safely remove them:

x = x
work_dir = work_dir

The second statement is pointless, you can safely remove it:

        sys.exit(2)
        sys.exit(0)

The string "/tmp/sec.lck" appears in many places in the file. It would be better to put it in a global variable at the top, for example:

LOCKFILE_PATH = "/tmp/sec.lck"

This is very tedious:

    dte = str(now.day) + "-" + str(now.month) + "-" + str(now.year)
    dte1 = str(now.hour) + ":" + str(now.minute) + ":" + str(now.second) + "." + str(now.microsecond)

You could write it simpler using the strftime method:

datestr = now.strftime('%d-%m-%Y')
timestr = now.strftime('%H:%M:%S')

The variable names dte and dte1 were poor, not describing what they are, so I tried to give them more meaningful names.


It would be better to not use sys.exit inside method calls. This kind of control is best to keep at a central point, for example in the main method, where you have the other condition checks that may end with sys.exit.


It would be better to move the entire content of the if __name__ == "__main__": block to a method called main like this:

def main():
    # ... (all the code you previously had in the `if`)

if __name__ == "__main__":
    main()
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.