Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #197800 > unrolled thread

get_used_memory

Started byLawrence D’Oliveiro <ldo@nz.invalid>
First post2026-06-12 03:46 +0000
Last post2026-06-14 23:56 +0000
Articles 18 — 3 participants

Back to article view | Back to comp.lang.python


Contents

  get_used_memory Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-06-12 03:46 +0000
    Re: get_used_memory Jon Ribbens <jon+usenet@unequivocal.eu> - 2026-06-12 07:18 +0000
      Re: get_used_memory Paul Rubin <no.email@nospam.invalid> - 2026-06-13 12:38 -0700
        Re: get_used_memory Jon Ribbens <jon+usenet@unequivocal.eu> - 2026-06-13 19:58 +0000
          Re: get_used_memory Jon Ribbens <jon+usenet@unequivocal.eu> - 2026-06-13 20:02 +0000
            Re: get_used_memory Paul Rubin <no.email@nospam.invalid> - 2026-06-13 14:13 -0700
              Re: get_used_memory Jon Ribbens <jon+usenet@unequivocal.eu> - 2026-06-13 21:35 +0000
                Re: get_used_memory Paul Rubin <no.email@nospam.invalid> - 2026-06-13 15:20 -0700
                  Re: get_used_memory Jon Ribbens <jon+usenet@unequivocal.eu> - 2026-06-13 22:53 +0000
                    Re: get_used_memory Paul Rubin <no.email@nospam.invalid> - 2026-06-14 17:23 -0700
                      Re: get_used_memory Jon Ribbens <jon+usenet@unequivocal.eu> - 2026-06-15 00:40 +0000
                        Re: get_used_memory Paul Rubin <no.email@nospam.invalid> - 2026-06-14 18:18 -0700
                          Re: get_used_memory Jon Ribbens <jon+usenet@unequivocal.eu> - 2026-06-15 07:20 +0000
                            Re: get_used_memory Paul Rubin <no.email@nospam.invalid> - 2026-06-15 12:02 -0700
                  Re: get_used_memory Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-06-14 01:10 +0000
        Re: get_used_memory Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-06-14 01:09 +0000
          Re: get_used_memory Paul Rubin <no.email@nospam.invalid> - 2026-06-14 01:28 -0700
            Re: get_used_memory Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-06-14 23:56 +0000

#197800 — get_used_memory

FromLawrence D’Oliveiro <ldo@nz.invalid>
Date2026-06-12 03:46 +0000
Subjectget_used_memory
Message-ID<110fvf3$1tqe3$1@dont-email.me>
So I looked at the example Gambas program at
<https://gambaswiki.org/wiki/doc/whatisgambas> and marvelled at its
unnecessary complexity (UUOC, even). It’s like PHP with variable
declarations!

Here’s my version: excluding header comments and blank lines and
shebang line, it’s about half the size.

info = dict \
  (
    (entry[0][:-1], int(entry[-2]))
    for line in open("/proc/meminfo", "rt")
    for entry in (tuple(s.strip() for s in line.split(" ")),)
    if entry[-2] != ""
  )
print("Used memory: %d Kb" % (info["MemTotal"] - info["MemFree"] - info["Buffers"] - info["Cached"] + info["SwapTotal"] - info["SwapFree"] - info["SwapCached"]))

[toc] | [next] | [standalone]


#197801

FromJon Ribbens <jon+usenet@unequivocal.eu>
Date2026-06-12 07:18 +0000
Message-ID<slrn112nclh.5fs.jon+usenet@raven.unequivocal.eu>
In reply to#197800
On 2026-06-12, Lawrence D’Oliveiro <ldo@nz.invalid> wrote:
> So I looked at the example Gambas program at
><https://gambaswiki.org/wiki/doc/whatisgambas> and marvelled at its
> unnecessary complexity (UUOC, even). It’s like PHP with variable
> declarations!
>
> Here’s my version: excluding header comments and blank lines and
> shebang line, it’s about half the size.
>
> info = dict \
>   (
>     (entry[0][:-1], int(entry[-2]))
>     for line in open("/proc/meminfo", "rt")
>     for entry in (tuple(s.strip() for s in line.split(" ")),)
>     if entry[-2] != ""
>   )
> print("Used memory: %d Kb" % (info["MemTotal"] - info["MemFree"] - info["Buffers"] - info["Cached"] + info["SwapTotal"] - info["SwapFree"] - info["SwapCached"]))

Better:

  with open('/proc/meminfo') as meminfo:
      info = {
          entry[0][:-1]: int(entry[1])
          for line in meminfo
          if (entry := line.split())
      }
  print('Used memory: %d kB' % (
      info['MemTotal'] - info['MemFree'] - info['Buffers'] - info['Cached'] +
      info['SwapTotal'] - info['SwapFree'] - info['SwapCached']
  ))

[toc] | [prev] | [next] | [standalone]


#197803

FromPaul Rubin <no.email@nospam.invalid>
Date2026-06-13 12:38 -0700
Message-ID<8733yq9qov.fsf@nightsong.com>
In reply to#197801
Jon Ribbens <jon+usenet@unequivocal.eu> writes:
>   with open('/proc/meminfo') as meminfo:
>       info = {
>           entry[0][:-1]: int(entry[1])
>           for line in meminfo
>           if (entry := line.split())
>       }

with open('/proc/meminfo') as meminfo:
    info = dict(line.split()[:2] for line in meminfo)

[toc] | [prev] | [next] | [standalone]


#197804

FromJon Ribbens <jon+usenet@unequivocal.eu>
Date2026-06-13 19:58 +0000
Message-ID<slrn112rdj8.5fs.jon+usenet@raven.unequivocal.eu>
In reply to#197803
On 2026-06-13, Paul Rubin <no.email@nospam.invalid> wrote:
> Jon Ribbens <jon+usenet@unequivocal.eu> writes:
>>   with open('/proc/meminfo') as meminfo:
>>       info = {
>>           entry[0][:-1]: int(entry[1])
>>           for line in meminfo
>>           if (entry := line.split())
>>       }
>
> with open('/proc/meminfo') as meminfo:
>     info = dict(line.split()[:2] for line in meminfo)

An excellent point, although it does mean the ':' characters remain
in the dictionary keys.

[toc] | [prev] | [next] | [standalone]


#197805

FromJon Ribbens <jon+usenet@unequivocal.eu>
Date2026-06-13 20:02 +0000
Message-ID<slrn112rdrf.5fs.jon+usenet@raven.unequivocal.eu>
In reply to#197804
On 2026-06-13, Jon Ribbens <jon+usenet@unequivocal.eu> wrote:
> On 2026-06-13, Paul Rubin <no.email@nospam.invalid> wrote:
>> Jon Ribbens <jon+usenet@unequivocal.eu> writes:
>>>   with open('/proc/meminfo') as meminfo:
>>>       info = {
>>>           entry[0][:-1]: int(entry[1])
>>>           for line in meminfo
>>>           if (entry := line.split())
>>>       }
>>
>> with open('/proc/meminfo') as meminfo:
>>     info = dict(line.split()[:2] for line in meminfo)
>
> An excellent point, although it does mean the ':' characters remain
> in the dictionary keys.

Oh, and doesn't have ints as the dictionary values, which is rather
more fatal to the use-case.

[toc] | [prev] | [next] | [standalone]


#197806

FromPaul Rubin <no.email@nospam.invalid>
Date2026-06-13 14:13 -0700
Message-ID<878q8i87p7.fsf@nightsong.com>
In reply to#197805
Jon Ribbens <jon+usenet@unequivocal.eu> writes:

> Oh, and doesn't have ints as the dictionary values, which is rather
> more fatal to the use-case.

> print("Used memory: %d Kb" % (info["MemTotal"] - info["MemFree"] - info["Buffers"] - info["Cached"] + info["SwapTotal"] - info["SwapFree"] - info["SwapCached"]))

It really should look at the units in the meminfo file too, but anyway,

alloced = ['MemTotal', 'SwapTotal']
free = ['MemFree, 'Buffers', 'Cached', 'SwapFree', 'SwapCached']

def total(xs): return sum(int(info[f'{x}:']) for x in xs)
print(f''Used memory: {total(alloced) - total(free)} Kb')

[toc] | [prev] | [next] | [standalone]


#197807

FromJon Ribbens <jon+usenet@unequivocal.eu>
Date2026-06-13 21:35 +0000
Message-ID<slrn112rj8p.5fs.jon+usenet@raven.unequivocal.eu>
In reply to#197806
On 2026-06-13, Paul Rubin <no.email@nospam.invalid> wrote:
> Jon Ribbens <jon+usenet@unequivocal.eu> writes:
>
>> Oh, and doesn't have ints as the dictionary values, which is rather
>> more fatal to the use-case.
>
>> print("Used memory: %d Kb" % (info["MemTotal"] - info["MemFree"] - info["Buffers"] - info["Cached"] + info["SwapTotal"] - info["SwapFree"] - info["SwapCached"]))
>
> It really should look at the units in the meminfo file too, but anyway,

Yes, although that's not entirely possible since proc_meminfo(5) doesn't
document what units are possible (although in actual fact it appears
that every line is hard-coded to either say 'kB' or no unit, no other
options are available and which lines have 'kB' or not never changes).

> alloced = ['MemTotal', 'SwapTotal']
> free = ['MemFree, 'Buffers', 'Cached', 'SwapFree', 'SwapCached']
>
> def total(xs): return sum(int(info[f'{x}:']) for x in xs)
> print(f''Used memory: {total(alloced) - total(free)} Kb')

Yes, obviously it is physically possible to write the code to cope with
the altered data structure. Just, there's a reason that neither my nor
Lawrence's version used your neat dict(line.split()[:2] ...) trick.

[toc] | [prev] | [next] | [standalone]


#197808

FromPaul Rubin <no.email@nospam.invalid>
Date2026-06-13 15:20 -0700
Message-ID<874ij684ls.fsf@nightsong.com>
In reply to#197807
Jon Ribbens <jon+usenet@unequivocal.eu> writes:
> Lawrence's version used your neat dict(line.split()[:2] ...) trick.

Maybe this:

   dict((a,int(b)) for a,b in (x.split()[:2] for x in xs))

I feel like there should be a way to do this with the := operator
instead of the nested generators, but it doesn't seem to be there.

[toc] | [prev] | [next] | [standalone]


#197809

FromJon Ribbens <jon+usenet@unequivocal.eu>
Date2026-06-13 22:53 +0000
Message-ID<slrn112rnrs.5fs.jon+usenet@raven.unequivocal.eu>
In reply to#197808
On 2026-06-13, Paul Rubin <no.email@nospam.invalid> wrote:
> Jon Ribbens <jon+usenet@unequivocal.eu> writes:
>> Lawrence's version used your neat dict(line.split()[:2] ...) trick.
>
> Maybe this:
>
>    dict((a,int(b)) for a,b in (x.split()[:2] for x in xs))
>
> I feel like there should be a way to do this with the := operator
> instead of the nested generators, but it doesn't seem to be there.

That was the way my version did it? If I use abbreviated variable names
like your version, it's actually shorter than yours ;-)

     {e[0][:-1]: int(e[1]) for x in xs if (e := x.split())}

[toc] | [prev] | [next] | [standalone]


#197814

FromPaul Rubin <no.email@nospam.invalid>
Date2026-06-14 17:23 -0700
Message-ID<877bo07itf.fsf@nightsong.com>
In reply to#197809
Jon Ribbens <jon+usenet@unequivocal.eu> writes:
>      {e[0][:-1]: int(e[1]) for x in xs if (e := x.split())}

Does this work?

 { a : int(b)) for x in xs if (a,b := x.split()) }

I think it's ok to keep the ':' in the field name.  Otherwise

 { a.rstrip(':') : int(b)) for x in xs if (a,b := x.split()) }

seems a bit more explicit at the expense of a few more chars.

[toc] | [prev] | [next] | [standalone]


#197815

FromJon Ribbens <jon+usenet@unequivocal.eu>
Date2026-06-15 00:40 +0000
Message-ID<slrn112uifb.5fs.jon+usenet@raven.unequivocal.eu>
In reply to#197814
On 2026-06-15, Paul Rubin <no.email@nospam.invalid> wrote:
> Jon Ribbens <jon+usenet@unequivocal.eu> writes:
>>      {e[0][:-1]: int(e[1]) for x in xs if (e := x.split())}
>
> Does this work?
>
>  { a : int(b)) for x in xs if (a,b := x.split()) }

No, for three reasons. Firstly, the lines with units result in x.split()
having 3 members, so you can't assign it to a 2-tuple. Secondly, it
appears that (a, b := x) means "create a tuple whose first member is
a and whose second member is x, and also assign x to b", which is not
at all what we need. Thirdly, if we fix that second one by saying
((a, b) := x.split()), you get "SyntaxError: cannot use assignment
expressions with tuple". (Assignment expressions are weirdly limited
for no apparent reason.)

> I think it's ok to keep the ':' in the field name.  Otherwise
>
>  { a.rstrip(':') : int(b)) for x in xs if (a,b := x.split()) }
>
> seems a bit more explicit at the expense of a few more chars.

a[:-1] would work and is shorter. But yeah it doesn't matter much.

[toc] | [prev] | [next] | [standalone]


#197816

FromPaul Rubin <no.email@nospam.invalid>
Date2026-06-14 18:18 -0700
Message-ID<87tsr461p9.fsf@nightsong.com>
In reply to#197815
Jon Ribbens <jon+usenet@unequivocal.eu> writes:
>>  { a : int(b)) for x in xs if (a,b := x.split()) }
> No, for three reasons. Firstly, the lines with units result in x.split()
> having 3 members, so you can't assign it to a 2-tuple.

Oh yes I had intended to say x.split()[:2] but somehow left that out.

> Secondly, it appears that (a, b := x) means "create a tuple whose
> first member is a and whose second member is x, and also assign x to
> b", which is not at all what we need.

Yuck, I had expected tuple unpacking.  Sounds like a pitfall comparable
to "=" vs "==" that kept the := operator out of the language for so
long.  Oh well.

[toc] | [prev] | [next] | [standalone]


#197817

FromJon Ribbens <jon+usenet@unequivocal.eu>
Date2026-06-15 07:20 +0000
Message-ID<slrn112v9t5.5fs.jon+usenet@raven.unequivocal.eu>
In reply to#197816
On 2026-06-15, Paul Rubin <no.email@nospam.invalid> wrote:
> Jon Ribbens <jon+usenet@unequivocal.eu> writes:
>>>  { a : int(b)) for x in xs if (a,b := x.split()) }
>> No, for three reasons. Firstly, the lines with units result in x.split()
>> having 3 members, so you can't assign it to a 2-tuple.
>
> Oh yes I had intended to say x.split()[:2] but somehow left that out.
>
>> Secondly, it appears that (a, b := x) means "create a tuple whose
>> first member is a and whose second member is x, and also assign x to
>> b", which is not at all what we need.
>
> Yuck, I had expected tuple unpacking.  Sounds like a pitfall comparable
> to "=" vs "==" that kept the := operator out of the language for so
> long.  Oh well.

My biggest complaint about := is the arbitrary and mysterious
restrictions on what you can use on the left hand side. You can't
even say "a.b := c". The PEP that introduced ":=" barely even
mentions these restrictions, let alone discusses or explains them.

[toc] | [prev] | [next] | [standalone]


#197818

FromPaul Rubin <no.email@nospam.invalid>
Date2026-06-15 12:02 -0700
Message-ID<87pl1r62zn.fsf@nightsong.com>
In reply to#197817
Jon Ribbens <jon+usenet@unequivocal.eu> writes:
> My biggest complaint about := is the arbitrary and mysterious
> restrictions on what you can use on the left hand side. You can't
> even say "a.b := c". The PEP that introduced ":=" barely even
> mentions these restrictions, let alone discusses or explains them.

Yeah that's pretty annoying.  Haskell doesn't have destructive
assignments at all, but you can put the equivalent of match/case inside
expressions.  So, something like:
   
   fromList [(a, read b) | (a:b:_) <- words x | x <- xs] :: Map String Int

The vertical bar is like "for" in Python's list comprehensions, "read"
is like int(str) except it converts to arbitrary datatypes, "words" is
like "split", and ":: Map String Int" is a type annotation that says
it's making a dictionary mapping strings to Ints.  The Int type
signature tells "read" to convert to ints instead of floats or whatever.
Finally, (a:b:_) binds the first two elements of x.split() and throws
away the rest.

I haven't tested the above so maybe I did something dumb.  I haven't
written any Haskell in a while.

[toc] | [prev] | [next] | [standalone]


#197811

FromLawrence D’Oliveiro <ldo@nz.invalid>
Date2026-06-14 01:10 +0000
Message-ID<110kv1c$3a32m$8@dont-email.me>
In reply to#197808
On Sat, 13 Jun 2026 15:20:31 -0700, Paul Rubin wrote:

> I feel like there should be a way to do this with the := operator
> instead of the nested generators, but it doesn't seem to be there.

You feel like there are lots of things you could do with the :=
operator ... if it were actually of any use.

[toc] | [prev] | [next] | [standalone]


#197810

FromLawrence D’Oliveiro <ldo@nz.invalid>
Date2026-06-14 01:09 +0000
Message-ID<110kuvc$3a32m$7@dont-email.me>
In reply to#197803
On Sat, 13 Jun 2026 12:38:08 -0700, Paul Rubin wrote:

> with open('/proc/meminfo') as meminfo:
>     info = dict(line.split()[:2] for line in meminfo)

Output on my machine of

    print("Used memory: %d Kb" % (info["MemTotal"] - info["MemFree"] - info["Buffers"] - info["Cached"] + info["SwapTotal"] - info["SwapFree"] - info["SwapCached"]))

from my version:

    Used memory: 13646656 Kb

From your version:

    ---------------------------------------------------------------------------
    KeyError                                  Traceback (most recent call last)
    Cell In[3], line 3
          1 with open('/proc/meminfo') as meminfo:
          2     info = dict(line.split()[:2] for line in meminfo)
    ----> 3 print("Used memory: %d Kb" % (info["MemTotal"] - info["MemFree"] - info["Buffers"] - info["Cached"] + info["SwapTotal"] - info["SwapFree"] - info["SwapCached"]))

    KeyError: 'MemTotal'

Tisk-tisk ...

[toc] | [prev] | [next] | [standalone]


#197812

FromPaul Rubin <no.email@nospam.invalid>
Date2026-06-14 01:28 -0700
Message-ID<87se6p7cg7.fsf@nightsong.com>
In reply to#197810
Lawrence D’Oliveiro <ldo@nz.invalid> writes:
>     KeyError: 'MemTotal'

Yeah you have to use 'MemTotal:' as the key.  But, you still have to
convert the digit strings to integers.

[toc] | [prev] | [next] | [standalone]


#197813

FromLawrence D’Oliveiro <ldo@nz.invalid>
Date2026-06-14 23:56 +0000
Message-ID<110nf2u$3vra6$4@dont-email.me>
In reply to#197812
On Sun, 14 Jun 2026 01:28:40 -0700, Paul Rubin wrote:

> Yeah you have to use 'MemTotal:' as the key. But, you still have to
> convert the digit strings to integers.

“I could solve that problem in a fraction of the code, if I didn’t
have to solve it correctly.”

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web