Thread: [Pymoul-svn] SF.net SVN: pymoul: [88] pymoul/trunk/src/moul/osdependent
Status: Alpha
Brought to you by:
tiran
From: <ti...@us...> - 2007-01-27 21:30:32
|
Revision: 88 http://pymoul.svn.sourceforge.net/pymoul/?rev=88&view=rev Author: tiran Date: 2007-01-27 13:30:28 -0800 (Sat, 27 Jan 2007) Log Message: ----------- Better process info API Modified Paths: -------------- pymoul/trunk/src/moul/osdependent/__init__.py pymoul/trunk/src/moul/osdependent/win32/__init__.py Added Paths: ----------- pymoul/trunk/src/moul/osdependent/processinfo.py Removed Paths: ------------- pymoul/trunk/src/moul/osdependent/win32/enumprocesses.py Modified: pymoul/trunk/src/moul/osdependent/__init__.py =================================================================== --- pymoul/trunk/src/moul/osdependent/__init__.py 2007-01-26 19:03:20 UTC (rev 87) +++ pymoul/trunk/src/moul/osdependent/__init__.py 2007-01-27 21:30:28 UTC (rev 88) @@ -17,11 +17,11 @@ # """OS dependent code for linux, mac and win32 ->>> pids = getCurrentPids() +>>> pids = getPids() >>> len(pids) > 1 True ->>> pids = getCurrentPidNames() +>>> pids = getPidNames() >>> found = False >>> for pid, name in pids.items(): ... if name.lower().startswith('python'): @@ -36,6 +36,8 @@ import os import sys from moul.log import getLogger +from moul.osdependent.processinfo import getPids +from moul.osdependent.processinfo import getPidNames LOG = getLogger('moul.osdependent') @@ -57,7 +59,6 @@ NAMES = ('getMoulUserDataDir', ('getPyMoulDataDir', '_getPyMoulDataDir'), # as 'startMoul', 'isMoulRunning', - 'getCurrentPids', 'getCurrentPidNames', ) _marker = object() Added: pymoul/trunk/src/moul/osdependent/processinfo.py =================================================================== --- pymoul/trunk/src/moul/osdependent/processinfo.py (rev 0) +++ pymoul/trunk/src/moul/osdependent/processinfo.py 2007-01-27 21:30:28 UTC (rev 88) @@ -0,0 +1,235 @@ +# pyMoul - Python interface to Myst Online URU Live +# Copyright (C) 2007 Christian Heimes <christian (at) cheimes (dot) de> + +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., 59 +# Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +"""Get process informations + +API: + getPids() - list of ints/longs + getPidNames() - mapping pid -> name + getPidDetails(pid) - detailed informations about a process + getPidDetails('self') - detailed informations about current process + +>>> cur = os.getpid() +>>> exe = sys.executable +>>> pids = getPids() +>>> pids > 1 +True +>>> isinstance(pids[0], (int, long)) +>>> cur in pids +True + +>>> mapping = getPidNames() +>>> cur in mapping +>>> mapping[cur].lower() in cur +True + +>>> getPidDetails('self')['name'] == getPidDetails(cur)['name'] +True +>>> getPidDetails(cur)['name'] == mapping[cur] +True +""" +__author__ = "Christian Heimes" +__version__ = "$Id$" +__revision__ = "$Revision$" + +import os +import sys + +_plat = sys.platform.startswith +if _plat('linux'): + PLAT = 'linux' + import os.path +elif _plat('win') or _plat('cygwin'): + PLAT = 'win' + from ctypes import windll, c_ulong, sizeof, c_buffer, byref + PSAPI = windll.psapi + KERNEL = windll.kernel32 + PROCESS_QUERY_INFORMATION = 0x0400 + PROCESS_VM_READ = 0x0010 + PROCESS_FLAGS = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ +#elif _plat('darwin'): +# pass +else: + raise OSError("OS %s is not supported" % os.name) + +NULL = "\x00" + +class LinuxProcReader(object): + """Get process informations under Linux by reading /proc + + Tested under Linux, may work on other POSIX os with /proc, too. + """ + + def getPids(self): + """Get a list of pids + """ + pids = [] + for name in os.listdir('/proc'): + if os.path.isdir('/proc/' + name): + try: + pids.append(int(name)) + except ValueError: + pass + return pids + + def getPidNames(self): + """Get a list of pid -> name + """ + mapping = {} + for pid in self.getPids(): + name = self._readProcStatus(pid, searchkey='name') + if name is not None: + mapping[pid] = name + return mapping + + def getPidDetails(self, pid): + """Get detailed informations about a process + """ + details = self._readProcStatus(pid) + details.update(self._readProcOther(pid)) + details['cmdline'] = self._readProcCmdline(pid) + return details + + def _readProcStatus(self, pid, searchkey=None): + """Read and parse status informations for PID pid + + pid - pid as long or int or 'self' + + If searchkey is None the method returns a mapping of lower keys + to values (stripped). + If searchkey is given than the method immediatly returns the value + or returns None if they key can't be found. + """ + mapping = {} + try: + # read entiry file to avoid race conditions + lines = open('/proc/%s/status' % pid, 'r').readlines() + except IOError: + return None + for line in lines: + try: + key, value = line.split(':\t') + except ValueError: + continue + key = key.lower() + value = value.strip() + #if value.endswith(' kB'): + # value = value[:-3] + if key == searchkey: + return value + mapping[key.lower()] = value + if searchkey is not None: + return None + return mapping + + def _readProcCmdline(self, pid): + """Read cmdline informations for pid and returns a list similar to sys.argv + """ + try: + # read entiry file to avoid race conditions + data = open('/proc/%s/cmdline' % pid, 'r').read() + except IOError: + return None + return data.split(NULL) + + def _readProcOther(self, pid): + """Read other possible useful things + + cwd -> current work directory (may not exist) + exe -> path to executable (may not exist) + """ + return { + 'cwd' : os.path.realpath('/proc/%s/cwd' % pid), + 'exe' : os.path.realpath('/proc/%s/exe' % pid), + } + +class WinEnumProcesses(object): + """""Get process informations under Win32 with psapi.dll + + Based on enumprocesses from Eric Koome + http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/305279 + """ + def getPids(self): + """Get a list of pids + """ + arr = c_ulong * 256 + lpidProcess = arr() + cb = sizeof(lpidProcess) + cbNeeded = c_ulong() + + # Call Enumprocesses to get hold of process id's + PSAPI.EnumProcesses(byref(lpidProcess), cb, byref(cbNeeded)) + nReturned = cbNeeded.value/sizeof(c_ulong()) # number of processes returned + return [pid for pid in lpidProcess][:nReturned] + + def getPidNames(self): + """Get a list of pid -> name + """ + hModule = c_ulong() + count = c_ulong() + modname = c_buffer(51) + mapping = [] + for pid in self.getPids(): + # Get handle to the process based on PID + hProcess = KERNEL.OpenProcess(PROCESS_FLAGS, False, pid) + if hProcess: + PSAPI.EnumProcessModules(hProcess, byref(hModule), + sizeof(hModule), byref(count)) + PSAPI.GetModuleBaseNameA(hProcess, hModule.value, modname, + sizeof(modname)) + name = u"".join([c for c in modname if c != NULL]) + modname[:] = sizeof(modname) * NULL + KERNEL.CloseHandle(hProcess) + mapping[pid] = name + + return mapping + + def getPidDetails(self, pid): + """Get detailed informations about a process + """ + if pid == 'self': + pid = os.getpid() + + hModule = c_ulong() + count = c_ulong() + modname = c_buffer(51) + hProcess = KERNEL.OpenProcess(PROCESS_FLAGS, False, pid) + if not hProcess: + return None + + PSAPI.EnumProcessModules(hProcess, byref(hModule), + sizeof(hModule), byref(count)) + PSAPI.GetModuleBaseNameA(hProcess, hModule.value, modname, + sizeof(modname)) + name = u"".join([c for c in modname if c != NULL]) + KERNEL.CloseHandle(hProcess) + return {'name' : name} + + +# Initialize global methods +if PLAT == 'linux': + _enumProcesses = LinuxProcReader() +elif PLAT == 'win': + _enumProcesses = WinEnumProcesses() + +getPids = _enumProcesses.getPids +getPidNames = _enumProcesses.getPidNames +getPidDetails = _enumProcesses.getPidDetails + +if __name__ == '__main__': + print getPidNames() + print getPidDetails('self') Modified: pymoul/trunk/src/moul/osdependent/win32/__init__.py =================================================================== --- pymoul/trunk/src/moul/osdependent/win32/__init__.py 2007-01-26 19:03:20 UTC (rev 87) +++ pymoul/trunk/src/moul/osdependent/win32/__init__.py 2007-01-27 21:30:28 UTC (rev 88) @@ -26,8 +26,8 @@ from moul.osdependent.win32.winpath import get_homedir as getMyDocuments from moul.osdependent.win32.winpath import get_appdata as getAppdata -from moul.osdependent.win32.enumprocesses import enumProcesses from moul.log import getLogger +from moul.osdependent.processinfo import getPidNames LOG = getLogger('moul.win') @@ -67,18 +67,8 @@ def isMoulRunning(): """Test if MOUL or the launcher is running """ - for pid, name in getCurrentPidNames().items(): + for pid, name in getPidNames().items(): if name.lower() in PROCESSES: - return name.lower() + return pid, name.lower() return False -def getCurrentPids(): - """Returns mapping pid -> name - """ - return enumProcesses().keys() - - -def getCurrentPidNames(): - """Returns mapping pid -> name - """ - return enumProcesses() Deleted: pymoul/trunk/src/moul/osdependent/win32/enumprocesses.py =================================================================== --- pymoul/trunk/src/moul/osdependent/win32/enumprocesses.py 2007-01-26 19:03:20 UTC (rev 87) +++ pymoul/trunk/src/moul/osdependent/win32/enumprocesses.py 2007-01-27 21:30:28 UTC (rev 88) @@ -1,66 +0,0 @@ -""" -Enumerates active processes as seen under windows Task Manager on Win NT/2k/XP using PSAPI.dll -(new api for processes) and using ctypes.Use it as you please. - -Based on information from http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q175030&ID=KB;EN-US;Q175030 - -By Eric Koome -email ek...@ya... -license GPL - -http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/305279 -Title: getting process information on windows -Last Updated: 2004/09/22 -Version no: 1.3 - -Changed by Christian Heimes -""" - -from ctypes import windll, c_ulong, sizeof, c_buffer, byref - -PSAPI = windll.psapi -KERNEL = windll.kernel32 -PROCESS_QUERY_INFORMATION = 0x0400 -PROCESS_VM_READ = 0x0010 -PROCESS_FLAGS = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ -NULL = '\x00' - -def enumProcesses(): - """Enumerate processes on Windows using psapi.dll - - @return: A mapping of pid(long) -> process name(unicode) - """ - result = {} - arr = c_ulong * 256 - lpidProcess = arr() - cb = sizeof(lpidProcess) - cbNeeded = c_ulong() - hModule = c_ulong() - count = c_ulong() - modname = c_buffer(51) - - # Call Enumprocesses to get hold of process id's - PSAPI.EnumProcesses(byref(lpidProcess), cb, byref(cbNeeded)) - nReturned = cbNeeded.value/sizeof(c_ulong()) # number of processes returned - pidProcess = [pid for pid in lpidProcess][:nReturned] - - for pid in pidProcess: - # Get handle to the process based on PID - hProcess = KERNEL.OpenProcess(PROCESS_FLAGS, False, pid) - if hProcess: - PSAPI.EnumProcessModules(hProcess, byref(hModule), - sizeof(hModule), byref(count)) - PSAPI.GetModuleBaseNameA(hProcess, hModule.value, modname, - sizeof(modname)) - - name = u"".join([c for c in modname if c != NULL]) - result[pid] = name - - modname[:] = sizeof(modname) * NULL - KERNEL.CloseHandle(hProcess) - - return result - -if __name__ == '__main__': - from pprint import pprint - pprint(EnumProcesses()) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ti...@us...> - 2007-03-19 21:58:26
|
Revision: 267 http://pymoul.svn.sourceforge.net/pymoul/?rev=267&view=rev Author: tiran Date: 2007-03-19 13:56:14 -0700 (Mon, 19 Mar 2007) Log Message: ----------- Fixed typo in getPyMoulDataDir Modified Paths: -------------- pymoul/trunk/src/moul/osdependent/darwin/__init__.py pymoul/trunk/src/moul/osdependent/linux/__init__.py Modified: pymoul/trunk/src/moul/osdependent/darwin/__init__.py =================================================================== --- pymoul/trunk/src/moul/osdependent/darwin/__init__.py 2007-03-19 13:35:53 UTC (rev 266) +++ pymoul/trunk/src/moul/osdependent/darwin/__init__.py 2007-03-19 20:56:14 UTC (rev 267) @@ -28,7 +28,7 @@ LOG = getLogger('moul.darwin') -LOG.critical('Darwin/Mac support is not tested') +LOG.warning('Mac/Darwin support is experimental') HOME = os.path.expanduser('~') MOUL_DIR = "%s/Library/Preferences/UruLive/Preferences/p_drive/My Documents/Uru Live" % HOME @@ -53,7 +53,7 @@ def getPyMoulDataDir(): """Get path to the pyMoul ini directory """ - return HOME, PYMOUL_DIR + return PYMOUL_DIR def getMoulInstallDir(): """Get path to MOUL install dir Modified: pymoul/trunk/src/moul/osdependent/linux/__init__.py =================================================================== --- pymoul/trunk/src/moul/osdependent/linux/__init__.py 2007-03-19 13:35:53 UTC (rev 266) +++ pymoul/trunk/src/moul/osdependent/linux/__init__.py 2007-03-19 20:56:14 UTC (rev 267) @@ -28,7 +28,7 @@ LOG = getLogger('moul.linux') -LOG.critical('Linux support is not tested') +LOG.warning('Linux support is experimental') HOME = os.path.expanduser('~') MOUL_DIR = "%s/.urulive" % HOME This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |