8

I would like to write a script to do an heavy network upload, in the background. However, I would like it to pause when I am using my computer (either by detecting network activity or keyboard activity or that I am not idle).

What is the best way to detect that I am using the computer, on Python on Unix?

Joseph Turian
  • 15,430
  • 14
  • 47
  • 62

5 Answers5

10

Unixy solution using X11/XScreenSaver to get idle time:

#!/usr/bin/python
import ctypes
import os

class XScreenSaverInfo( ctypes.Structure):
  """ typedef struct { ... } XScreenSaverInfo; """
  _fields_ = [('window',      ctypes.c_ulong), # screen saver window
              ('state',       ctypes.c_int),   # off,on,disabled
              ('kind',        ctypes.c_int),   # blanked,internal,external
              ('since',       ctypes.c_ulong), # milliseconds
              ('idle',        ctypes.c_ulong), # milliseconds
              ('event_mask',  ctypes.c_ulong)] # events

xlib = ctypes.cdll.LoadLibrary('libX11.so')
display = xlib.XOpenDisplay(os.environ['DISPLAY'])
xss = ctypes.cdll.LoadLibrary('libXss.so.1')
xss.XScreenSaverAllocInfo.restype = ctypes.POINTER(XScreenSaverInfo)
xssinfo = xss.XScreenSaverAllocInfo()
xss.XScreenSaverQueryInfo(display, xlib.XDefaultRootWindow(display), xssinfo)

print "idle: %d ms" % xssinfo.contents.idle

# cleanup
xss.XCloseDisplay(display)
xss.XFree(xssinfo)

(From "X11 idle time and focused window in Python", originally found on thp.io, now apparently only the GitHub gist by the same author survives.)

A cleanup section was added to the code in a later edit by another user so that it can be called periodically.

As noted in a comment to the answer they reference, note that you should also do proper return code checking on function calls to avoid ungraceful program termination when X display and other initializations fail for some reason.

peth
  • 235
  • 1
  • 5
  • You've accepted a solution that tells you whether or not the user is interacting with the input devices. But what's really going to burn is whether or not the network is busy. It's obviously your choice, but it seems odd to me. – David Heffernan May 07 '11 at 19:00
  • on my system you have to call `xss.XFree(xssinfo)` **after** reading `xssinfo.contents.idle`, or will be set to `0` – eadmaster Jan 29 '18 at 11:54
2

I guess that you are concerned about the network activity of the file transfer getting in the way of the interactive user. You don't need to worry about whether or not the user is typing on the keyboard. Really all that matters is whether or not there are competing network activities.

On Windows, for example, you can use Background Intelligent Transfer Service. This is the same service that Windows Update uses to deliver updates to your desktop without getting in the way of your use of the machine. To script it you might consider Powershell. If you are dead set on using Python you can do it with win32com.bits.

Other platforms will, no doubt, have similar offerings.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • I'm curious what the offering for Unix is. – Joseph Turian May 06 '11 at 17:58
  • @Joseph - For unix, `setsockopt(fd, IPPROTO_IP, IP_TOS, IPTOS_MINCOST)` should mark your networking data as less important than most other data. See `ip(7)` and `socket(7)` for more info. Combined with `nice(1)` or `setpriority(2)`, you could down-prioritize your application compared to any interactive apps present. – gnud May 06 '11 at 18:46
2

Most Linux distributions come with ConsoleKit, which provides some session information over DBus, including an "idle hint"; this works for both X11 and text logins.

(However, there are plans to deprecate ConsoleKit, moving parts of it into systemd; the future for the "idle hint" feature hasn't been decided yet.)


Just for completeness, os.stat(ttydev).st_mtime or os.fstat(1).st_mtime returns last input time for tty/pty devices.

user1686
  • 13,155
  • 2
  • 35
  • 54
0

Stick a webcam on your computer that grabs an image every five seconds, then there's some python modules for image analysis that can check if you are still sitting in your seat.

Or get a microswitch wired into your chair, connect that to your PC serial port (or one of those modern USB ports) and read that from Python...

Spacedman
  • 92,590
  • 12
  • 140
  • 224
0

import this script. When another app like firefox starts grabbing bandwidth, pause the main program. There's some simple addition involed but other than that it's pretty easy

SnobOverflow
  • 143
  • 1
  • 7
  • I think the challenge is in detecting that another app is demanding bandwidth. What's your suggestion for doing that? – David Heffernan May 06 '11 at 17:00
  • I'm terrible with networking, but couldn't he just define a class to count the packets, average the rate, then pause when it hits a predefined deviation from the norm? – SnobOverflow May 06 '11 at 17:09