Python standard library to get total memory size [duplicate] - python

This question already has answers here:
Get total physical memory in Python
(4 answers)
Closed 4 years ago.
I'm wondering if there is a module in python standard library I can use to get the total physical memory size. I know I can use psutil, but it would be great if my python script can run without installing external module. Thanks!
Edited:
Sorry guys, I forgot to mention that I'm using a mac OSX. Thanks for all the windows solutions tho!

If you're on Windows, you can use GlobalMemoryStatusEx, which requires only ctypes and no additional modules.
from ctypes import Structure, c_int32, c_uint64, sizeof, byref, windll
class MemoryStatusEx(Structure):
_fields_ = [
('length', c_int32),
('memoryLoad', c_int32),
('totalPhys', c_uint64),
('availPhys', c_uint64),
('totalPageFile', c_uint64),
('availPageFile', c_uint64),
('totalVirtual', c_uint64),
('availVirtual', c_uint64),
('availExtendedVirtual', c_uint64)]
def __init__(self):
self.length = sizeof(self)
Used like this:
>>> m = MemoryStatusEx()
>>> assert windll.kernel32.GlobalMemoryStatusEx(byref(m))
>>> print('You have %0.2f GiB of RAM installed' % (m.totalPhys / (1024.)**3))
See here, here, and here for information for MAC OS X/other UNIX systems.

I've utilized this function in a Windows environment previously.
import os
process = os.popen('wmic memorychip get capacity')
result = process.read()
process.close()
totalMem = 0
for m in result.split(" \r\n")[1:-1]:
totalMem += int(m)
print totalMem / (1024**3)
This utilizes wmic and the following command wmic memorychip get capacity, which you can run from your command line to see output in bytes.
This command reads the capacity of each memory module in the machine (in bytes) and then converts the total to gigabytes.
Example:
> wmic memorychip get capacity
Capacity
4294967296
4294967296
This shows I have two 4 GB chips.
> python get_totalmemory.py
8
Adding those two module capacities and doing a quick conversion shows I have 8 GB of RAM on this machine.

Based on this discussion there seems to nothing in Python's standard library that'll do that. Here's a few that might help:
Python System
Information
Psutil (Up-to-date, good cross
platform support, I've used this before, not in Blender though)
SIGAR (looks fairly
recent, supports a number of platforms)

Related

Gio.MemoryInputStream does not free memory when closed

Running Python 3.4 on Windows 7, the close function of Gio.MemoryInputStream does not free the memory, as it should. The test code is :
from gi.repository import Gio
import os, psutil
process = psutil.Process(os.getpid())
for i in range (1,10) :
input_stream = Gio.MemoryInputStream.new_from_data(b"x" * 10**7)
x = input_stream.close_async(2)
y = int(process.memory_info().rss / 10**6) # Get the size of memory used by the program
print (x, y)
This returns :
True 25
True 35
True 45
True 55
True 65
True 75
True 85
True 95
True 105
This shows that on each loop, the memory used by the program increases of 10 MB, even if the close function returned True.
How is it possible to free the memory, once the Stream is closed ?
Another good solution would be to reuse the stream. But set_data or replace_data raises the following error :
'Data access methods are unsupported. Use normal Python attributes instead'
Fine, but which property ?
I need a stream in memory in Python 3.4. I create a Pdf File with PyPDF2, and then I want to preview it with Poppler. Due to a bug in Poppler (see Has anyone been able to use poppler new_from_data in python?) I cannot use the new_from_data function and would like to use the new_from_stream function.
This is a bug in GLib’s Python bindings which can’t be trivially fixed.
Instead, you should use g_memory_input_stream_new_from_bytes(), which handles freeing memory differently, and shouldn’t suffer from the same bug.
In more detail, the bug with new_from_data() is caused by the introspection annotations, which GLib uses to allow language bindings to automatically expose all of its API, not supporting the GDestroyNotify parameter for new_from_data() which needs to be set to a non-NULL function to free the allocated memory which is passed in to the other arguments. Running your script under gdb shows that pygobject passes NULL to the GDestroyNotify parameter. It can’t do any better, since there is currently no way of expressing that the memory management semantics of the data parameter depend on what’s passed to destroy.
Thanks for your answer, #Philip Withnall. I tested the solution you propose, and it works. To help others to understand, here is my test code :
from gi.repository import Gio, GLib
import os, psutil
process = psutil.Process(os.getpid())
for i in range (1,10) :
input_stream = Gio.MemoryInputStream.new_from_bytes(GLib.Bytes(b"x" * 10**7))
x = input_stream.close()
y = int(process.memory_info().rss / 10**6) # Get the size of memory used by the program
print (x, y)
Now y non longer grows.

Python - How to get the start/base address of a process?

How do I get the start/base address of a process? Per example Solitaire.exe (solitaire.exe+BAFA8)
#-*- coding: utf-8 -*-
import ctypes, win32ui, win32process
PROCESS_ALL_ACCESS = 0x1F0FFF
HWND = win32ui.FindWindow(None,u"Solitär").GetSafeHwnd()
PID = win32process.GetWindowThreadProcessId(HWND)[1]
PROCESS = ctypes.windll.kernel32.OpenProcess(PROCESS_ALL_ACCESS,False,PID)
print PID, HWND,PROCESS
I would like to calculate a memory address and for this way I need the base address of solitaire.exe.
Here's a picture of what I mean:
I think the handle returned by GetModuleHandle is actually the base address of the given module. You get the handle of the exe by passing NULL.
Install pydbg
Source: https://github.com/OpenRCE/pydbg
Unofficial binaries here: http://www.lfd.uci.edu/~gohlke/pythonlibs/#pydbg
from pydbg import *
from pydbg.defines import *
import struct
dbg = pydbg()
path_exe = "C:\\windows\\system32\\calc.exe"
dbg.load(path_exe, "-u amir")
dbg.debug_event_loop()
parameter_addr = dbg.context.Esp #(+ 0x8)
print 'ESP (address) ',parameter_addr
#attach not working under Win7 for me
#pid = raw_input("Enter PID:")
#print 'PID entered %i'%int(pid)
#dbg.attach(int(pid)) #attaching to running process not working
You might want to have a look at PaiMei, although it's not very active right now https://github.com/OpenRCE/paimei
I couldn't get attach() to work and used load instead. Pydbg has loads of functionality, such as read_proccess_memory, write_process_memory etc.
Note that you can't randomly change memory, because an operating system protects memory of other processes from your process (protected mode). Before the x86 processors there were some which allowed all processors to run in real mode, i.e. the full access of memory for every programm. Non-malicious software usually (always?) doesn't read/write other processes' memory.
The HMDOULE value of GetModuleHandle is the base address of the loaded module and is probably the address you need to compute the offset.
If not, that address is the start of the header of the module (DLL/EXE), which can be displayed with the dumpbin utility that comes with Visual Studio or you can interpret it yourself using the Microsoft PE and COFF Specification to determine the AddressOfEntryPoint and BaseOfCode as offsets from the base address. If the base address of the module isn't what you need, one of these two is another option.
Example:
>>> BaseAddress = win32api.GetModuleHandle(None) + 0xBAFA8
>>> print '{:08X}'.format(BaseAddress)
1D0BAFA8
If The AddressOfEntryPoint or BaseOfCode is needed, you'll have to use ctypes to call ReadProcessMemory following the PE specification to locate the offsets, or just use dumpbin /headers solitaire.exe to learn the offsets.
You can use frida to easy do that.
It is very useful to make hack and do some memory operation just like make address offset, read memory, write something to special memory etc...
https://github.com/frida/frida
2021.08.01 update:
Thanks for #Simas Joneliunas reminding
There some step using frida(windows):
Install frida by pip
pip install frida-tools # CLI tools
pip install frida # Python bindings
Using frida api
session = frida.attach(processName)
script = session.create_script("""yourScript""")
script.load()
sys.stdin.read() #make program always alive
session.detach()
Edit your scrip(using JavaScrip)
var baseAddr = Module.findBaseAddress('solitaire.exe');
var firstPointer = baseAddr.add(0xBAFA8).readPointer();
var secondPointer = firstPointer.add(0x50).readPointer();
var thirdPointer = secondPointer.add(0x14).readPointer();
#if your target pointer points to a Ansi String, you can use #thirdPointer.readAnsiString() to read
The official site https://frida.re/

Available disk space on an SMB share, via Python

Does anyone know a way to get the amount of space available on a Windows (Samba) share via Python 2.6 with its standard library? (also running on Windows)
e.g.
>>> os.free_space("\\myshare\folder") # return free disk space, in bytes
1234567890
If PyWin32 is available:
free, total, totalfree = win32file.GetDiskFreeSpaceEx(r'\\server\share')
Where free is a amount of free space available to the current user, and totalfree is amount of free space total. Relevant documentation: PyWin32 docs, MSDN.
If PyWin32 is not guaranteed to be available, then for Python 2.5 and higher there is ctypes module in stdlib. Same function, using ctypes:
import sys
from ctypes import *
c_ulonglong_p = POINTER(c_ulonglong)
_GetDiskFreeSpace = windll.kernel32.GetDiskFreeSpaceExW
_GetDiskFreeSpace.argtypes = [c_wchar_p, c_ulonglong_p, c_ulonglong_p, c_ulonglong_p]
def GetDiskFreeSpace(path):
if not isinstance(path, unicode):
path = path.decode('mbcs') # this is windows only code
free, total, totalfree = c_ulonglong(0), c_ulonglong(0), c_ulonglong(0)
if not _GetDiskFreeSpace(path, pointer(free), pointer(total), pointer(totalfree)):
raise WindowsError
return free.value, total.value, totalfree.value
Could probably be done better but I'm not really familiar with ctypes.
The standard library has the os.statvfs() function, but unfortunately it's only available on Unix-like platforms.
In case there is some cygwin-python maybe it would work there?

calling Objective C functions from Python?

Is there a way to dynamically call an Objective C function from Python?
For example, On the mac I would like to call this Objective C function
[NSSpeechSynthesizer availableVoices]
without having to precompile any special Python wrapper module.
As others have mentioned, PyObjC is the way to go. But, for completeness' sake, here's how you can do it with ctypes, in case you need it to work on versions of OS X prior to 10.5 that do not have PyObjC installed:
import ctypes
import ctypes.util
# Need to do this to load the NSSpeechSynthesizer class, which is in AppKit.framework
appkit = ctypes.cdll.LoadLibrary(ctypes.util.find_library('AppKit'))
objc = ctypes.cdll.LoadLibrary(ctypes.util.find_library('objc'))
objc.objc_getClass.restype = ctypes.c_void_p
objc.sel_registerName.restype = ctypes.c_void_p
objc.objc_msgSend.restype = ctypes.c_void_p
objc.objc_msgSend.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
# Without this, it will still work, but it'll leak memory
NSAutoreleasePool = objc.objc_getClass('NSAutoreleasePool')
pool = objc.objc_msgSend(NSAutoreleasePool, objc.sel_registerName('alloc'))
pool = objc.objc_msgSend(pool, objc.sel_registerName('init'))
NSSpeechSynthesizer = objc.objc_getClass('NSSpeechSynthesizer')
availableVoices = objc.objc_msgSend(NSSpeechSynthesizer, objc.sel_registerName('availableVoices'))
count = objc.objc_msgSend(availableVoices, objc.sel_registerName('count'))
voiceNames = [
ctypes.string_at(
objc.objc_msgSend(
objc.objc_msgSend(availableVoices, objc.sel_registerName('objectAtIndex:'), i),
objc.sel_registerName('UTF8String')))
for i in range(count)]
print voiceNames
objc.objc_msgSend(pool, objc.sel_registerName('release'))
It ain't pretty, but it gets the job done. The final list of available names is stored in the voiceNames variable above.
2012-4-28 Update: Fixed to work in 64-bit Python builds by making sure all parameters and return types are passed as pointers instead of 32-bit integers.
Since OS X 10.5, OS X has shipped with the PyObjC bridge, a Python-Objective-C bridge. It uses the BridgeSupport framework to map Objective-C frameworks to Python. Unlike, MacRuby, PyObjC is a classical bridge--there is a proxy object on the python side for each ObjC object and visa versa. The bridge is pretty seamless, however, and its possible to write entire apps in PyObjC (Xcode has some basic PyObjC support, and you can download the app and file templates for Xcode from the PyObjC SVN at the above link). Many folks use it for utilities or for app-scripting/plugins. Apple's developer site also has an introduction to developing Cocoa applications with Python via PyObjC which is slightly out of date, but may be a good overview for you.
In your case, the following code will call [NSSpeechSynthesizer availableVoices]:
from AppKit import NSSpeechSynthesizer
NSSpeechSynthesizer.availableVoices()
which returns
(
"com.apple.speech.synthesis.voice.Agnes",
"com.apple.speech.synthesis.voice.Albert",
"com.apple.speech.synthesis.voice.Alex",
"com.apple.speech.synthesis.voice.BadNews",
"com.apple.speech.synthesis.voice.Bahh",
"com.apple.speech.synthesis.voice.Bells",
"com.apple.speech.synthesis.voice.Boing",
"com.apple.speech.synthesis.voice.Bruce",
"com.apple.speech.synthesis.voice.Bubbles",
"com.apple.speech.synthesis.voice.Cellos",
"com.apple.speech.synthesis.voice.Deranged",
"com.apple.speech.synthesis.voice.Fred",
"com.apple.speech.synthesis.voice.GoodNews",
"com.apple.speech.synthesis.voice.Hysterical",
"com.apple.speech.synthesis.voice.Junior",
"com.apple.speech.synthesis.voice.Kathy",
"com.apple.speech.synthesis.voice.Organ",
"com.apple.speech.synthesis.voice.Princess",
"com.apple.speech.synthesis.voice.Ralph",
"com.apple.speech.synthesis.voice.Trinoids",
"com.apple.speech.synthesis.voice.Vicki",
"com.apple.speech.synthesis.voice.Victoria",
"com.apple.speech.synthesis.voice.Whisper",
"com.apple.speech.synthesis.voice.Zarvox"
)
(a bridged NSCFArray) on my SL machine.
Mac OS X from 10.5 onward has shipped with Python and the objc module that will let you do what you want.
An example:
from Foundation import *
thing = NSKeyedUnarchiver.unarchiveObjectWithFile_(some_plist_file)
You can find more documentation here.
You probably want PyObjC. That said, I've never actually used it myself (I've only ever seen demos), so I'm not certain that it will do what you need.

Finding the Current Active Window in Mac OS X using Python

Is there a way to find the application name of the current active window at a given time on Mac OS X using Python?
This should work:
#!/usr/bin/python
from AppKit import NSWorkspace
activeAppName = NSWorkspace.sharedWorkspace().activeApplication()['NSApplicationName']
print activeAppName
Only works on Leopard, or on Tiger if you have PyObjC installed and happen to point at the right python binary in line one (not the case if you've installed universal MacPython, which you'd probably want to do on Tiger). But Peter's answer with the Carbon way of doing this will probably be quite a bit faster, since importing anything from AppKit in Python takes a while, or more accurately, importing something from AppKit for the first time in a Python process takes a while.
If you need this inside a PyObjC app, what I describe will work great and fast, since you only experience the lag of importing AppKit once. If you need this to work as a command-line tool, you'll notice the performance hit. If that's relevant to you, you're probably better off building a 10 line Foundation command line tool in Xcode using Peter's code as a starting point.
The method in the accepted answer was deprecated in OS X 10.7+. The current recommended version would be the following:
from AppKit import NSWorkspace
active_app_name = NSWorkspace.sharedWorkspace().frontmostApplication().localizedName()
print(active_app_name)
First off, do you want the window or the application name? This isn't Windows—an application process on Mac OS X can have multiple windows. (Furthermore, this has also been true of Windows for a few years now, although I have no idea what the API looks like for that.)
Second, Carbon or Cocoa?
To get the active window in Cocoa:
window = NSApp.mainWindow()
To get the name of your process in Cocoa:
appName = NSProcessInfo.processInfo().processName()
Edit: Oh, I think I know what you want. The name of the frontmost process, right?
I don't think there's a way to do it in Cocoa, but here's how to do it in Carbon in C:
ProcessSerialNumber psn = { 0L, 0L };
OSStatus err = GetFrontProcess(&psn);
/*error check*/
CFStringRef processName = NULL;
err = CopyProcessName(&psn, &processName);
/*error check*/
Remember to CFRelease(processName) when you're done with it.
I'm not sure what that will look like in Python, or if it's even possible. Python doesn't have pointers, which makes that tricky.
I know PyObjC would translate the latter argument to CopyProcessName into err, processName = CopyProcessName(…), but the Carbon bindings don't rely on PyObjC (they're part of core Python 2), and I'm not sure what you do about the PSN either way.
I needed the current frontmost application in a Python script that arranges the windows nicely on my screen (see move_window).
Of course, the complete credit goes to Peter! But here is the complete program:
#include <Carbon/Carbon.h>
int main(int, char) {
ProcessSerialNumber psn = { 0L, 0L };
OSStatus err = GetFrontProcess(&psn);
CFStringRef processName = NULL;
err = CopyProcessName(&psn, &processName);
printf("%s\n", CFStringGetCStringPtr(processName, NULL));
CFRelease(processName);
}
Build with gcc -framework Carbon filename.c

Categories