Hi Guys,
I am kind of new to python and started working on python from February2013.

I have a script which run on linux machine. It captures the available RAM from the system and then tries to eat it up. I am using subprocess.Popen('free',...) command and for first loop it works fine, but for second loop it throws an exception. Any clue on this. Code is below:

def get_Ram_avialable():
    try:
        print 'a1'
        process = Popen('free\n', stdout = PIPE, stderr = PIPE, shell = True)
        print 'a2'
        write_file  = open('dump.txt' , 'w')
        write_file.write(process)
        write_file.close()
        time.sleep(2)
        read_file    = open('dump.txt','r')  
        if 'Mem:' in line:
            raw_data  = line.split()
            used_bytes = raw_data[2]
            free_K_bytes = raw_data[3]
            print "\nMemory Used bytes :"+used_bytes,
            print ",  Free bytes :"+ free_K_bytes
        read_file.close()
        free_bytes = int(free_K_bytes)*1024 
        free_bytes = int(free_bytes)*(0.90)  # Takes 90% of available RAM
        os.remove('dump.txt')
        return int(free_bytes)

    except Exception, e:
        raise Exception("Exception while calculating the RAM")




 while True:
    fill_space = ' '*get_Ram_avialable()
    time.sleep(15)

Output is like this:
a1
a2

Memory Used bytes :70856 , Free bytes :54868
a1
Traceback (most recent call last):
File "./fillRAM.py", line 30, in <module>
fill_space = ' '*get_Ram_avialable()
File "./fillRAM.py", line 23, in get_Ram_avialable
raise Exception("Exception while calculating the RAM")
Exception: Exception while calculating the RAM

Edited 3 Years Ago by mksha: Formatted the string

Don't catch an exception only to raise a new one unless you know what you are doing! It hides the original exception and prevents debugging. So you could replace line 24 above with a naked raise statement to see where the error occured.

You can use the Command class from this snippet to call subprocess.Popen() more easily

class CommandFailed(Exception):
    pass

def get_ram_available():
    com = Command('free -b').run()
    if com.failed:
        raise CommandFailed(com.error)
    else:
        lines = com.output.splitlines()
        lines = [x for x in lines if 'Mem:' in x]
        if lines:
            assert len(lines) == 1
            L = lines[0].split()
            return int(L[3])
        else:
            raise RuntimeError('Unable to compute free ram')

Edited 3 Years Ago by Gribouillis

Hi Gribouillis,

When I try running this snippt i got error, I am not sure what I need to import, I tried with import commands

com = Command('free -b').run()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'Command' is not defined

Hey Sorry for over seeing the snippet you mentioned.. I will check it

Edited 3 Years Ago by mksha: oversight

Hi Gribouillis,

This is what I have now and the error below that which I got!!!
I think subprocess.Popen command is taking more RAM to operate than what is available. I lowered down the usage to 75% to consume but still I have the same response.

Any suggestion to deal with this issue and thanks alot for guiding me!!!!

class Command(object):
    """Run a command and capture it's output string, error string and exit status"""
    def __init__(self, command):
        self.command = command

    def run(self, shell=True):
        import subprocess as sp
        process = sp.Popen(self.command, shell = shell, stdout = sp.PIPE, stderr = sp.PIPE)
        self.pid = process.pid
        self.output, self.error = process.communicate()
        self.failed = process.returncode
        return self

    def returncode(self):
        return self.failed



class CommandFailed(Exception):
    pass


def get_ram_available():
    com = Command('free -b').run()
    if com.failed:
        raise CommandFailed(com.error)
    else:
        lines = com.output.splitlines()
        lines = [x for x in lines if 'Mem:' in x]
        if lines:
            assert len(lines) == 1
            L = lines[0].split()
            print int(L[3])
            return int(L[3])
        else:
            raise RuntimeError('Unable to compute free ram')

while True:
    value_K_bytes = get_ram_available()
    value_bytes  = value_K_bytes*1024*0.75  #takes 75% of ram
    print value_bytes


    fill_space = ' '* int(value_bytes)
    time.sleep(10)

OUTPUT IS AS BELOW:

69484
53363712.0
Traceback (most recent call last):
  File "./fillRAM.py", line 51, in <module>
    value_K_bytes = get_ram_available()
  File "./fillRAM.py", line 36, in get_ram_available
    com = Command('free -b').run()
  File "./fillRAM.py", line 20, in run
    process = sp.Popen(self.command, shell = shell, stdout = sp.PIPE, stderr = s
p.PIPE)
  File "/usr/lib/python2.7/subprocess.py", line 672, in __init__
  File "/usr/lib/python2.7/subprocess.py", line 1112, in _execute_child
OSError: [Errno 12] Cannot allocate memory

With free -b, the results should already be in bytes (not Kbytes). At least that's what man free says on my machine. Try without -b option if you want KB. Your program may take too much memory with the line fill_space = ' '* int(value_bytes). Why do you want to fill the ram ?

Edited 3 Years Ago by Gribouillis

For me it is showing in KB as I got this output:

64400 as return value and after hitting Free command on console then also 64400 is the total available memory.

I just wana stress the system to see if it responds to my another script which says"RAM is fully utilized"

This article has been dead for over six months. Start a new discussion instead.