Python Forum

Full Version: format the output from a nested dictionary.
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hello everyone im trying to make my codes output to look like this output,
without any trailing or leading symbols. Any tips on how i can do that?

The expected output should look like this.

Output:
| 0 | root | /bin/bash | 1 | bin | /usr/bin/nologin | 2 | daemon | /usr/bin/nologin | 1000 | nsa | /bin/bash
currentuser ={'root':{'uid': 0,'username': 'root' ,'shell': '/bin/bash'},
        'daemon': {'uid': 1,'username': 'daemon' ,'shell': '/usr/sbin/nologin'},
        'bin': {'uid': 2,'username': 'bin', 'shell':'/usr/sbin/nologin'},
        'nsa': {'uid': 1000,'username': 'nsa', 'shell': '/bin/bash'}}

for key, value in currentuser.items():
print(f"\nKey: {key}")
print(f"Value: {value}")
currentuser ={'root':{'uid': 0,'username': 'root' ,'shell': '/bin/bash'},
'daemon': {'uid': 1,'username': 'daemon' ,'shell': '/usr/sbin/nologin'},
'bin': {'uid': 2,'username': 'bin', 'shell':'/usr/sbin/nologin'},
'nsa': {'uid': 1000,'username': 'nsa', 'shell': '/bin/bash'}}

for v in currentuser.values():
    print(f'|{v["uid"]}|{v["username"]}|{v["shell"]}')
Output:
|0|root|/bin/bash |1|daemon|/usr/sbin/nologin |2|bin|/usr/sbin/nologin |1000|nsa|/bin/bash
If you want formatting, I prefer using a formatting package. tabulate has worked well for me.

from tabulate import tabulate

currentuser ={'root':{'uid': 0,'username': 'root' ,'shell': '/bin/bash'},
        'daemon': {'uid': 1,'username': 'daemon' ,'shell': '/usr/sbin/nologin'},
        'bin': {'uid': 2,'username': 'bin', 'shell':'/usr/sbin/nologin'},
        'nsa': {'uid': 1000,'username': 'nsa', 'shell': '/bin/bash'}}


columns = list(next(iter(currentuser.values())).keys())
print(tabulate([x.values() for x in currentuser.values()], headers=columns, tablefmt="presto"))
Output:
uid | username | shell -------+------------+------------------- 0 | root | /bin/bash 1 | daemon | /usr/sbin/nologin 2 | bin | /usr/sbin/nologin 1000 | nsa | /bin/bash
(May-02-2021, 11:19 PM)menator01 Wrote: [ -> ]
currentuser ={'root':{'uid': 0,'username': 'root' ,'shell': '/bin/bash'},
'daemon': {'uid': 1,'username': 'daemon' ,'shell': '/usr/sbin/nologin'},
'bin': {'uid': 2,'username': 'bin', 'shell':'/usr/sbin/nologin'},
'nsa': {'uid': 1000,'username': 'nsa', 'shell': '/bin/bash'}}

for v in currentuser.values():
    print(f'|{v["uid"]}|{v["username"]}|{v["shell"]}')
Output:
|0|root|/bin/bash |1|daemon|/usr/sbin/nologin |2|bin|/usr/sbin/nologin |1000|nsa|/bin/bash

Thanks for the reply i appreciate it. It works fine,
but i want this symbol | in the columns to align with eachother.
(May-03-2021, 01:54 AM)bowlofred Wrote: [ -> ]If you want formatting, I prefer using a formatting package. tabulate has worked well for me.

from tabulate import tabulate

currentuser ={'root':{'uid': 0,'username': 'root' ,'shell': '/bin/bash'},
        'daemon': {'uid': 1,'username': 'daemon' ,'shell': '/usr/sbin/nologin'},
        'bin': {'uid': 2,'username': 'bin', 'shell':'/usr/sbin/nologin'},
        'nsa': {'uid': 1000,'username': 'nsa', 'shell': '/bin/bash'}}


columns = list(next(iter(currentuser.values())).keys())
print(tabulate([x.values() for x in currentuser.values()], headers=columns, tablefmt="presto"))
Output:
uid | username | shell -------+------------+------------------- 0 | root | /bin/bash 1 | daemon | /usr/sbin/nologin 2 | bin | /usr/sbin/nologin 1000 | nsa | /bin/bash

Thanks for the reply appreciate it, but i want to do it without import,
and i want the output to look like i requested.
If you don't want to import, then you'll have to code it up.

Use len(str) to find the length of each of the elements in each column. Then use format strings to print each of the elements from that column in the correct length.

formats = ["<20", 10, 5]
data = [15, "Hello", "/bin/sh"]

print("".join(f"| {d:{f}}" for d,f in zip(data,formats)))
Output:
| 15 | Hello | /bin/sh
You can pass formatting with f-strings so little adjustment to menator01 code would deliver required result (numbers are aligned to right and text to left which is canonical way to display these datatypes in table style):

currentuser ={'root':{'uid': 0,'username': 'root' ,'shell': '/bin/bash'},
              'daemon': {'uid': 1,'username': 'daemon' ,'shell': '/usr/sbin/nologin'},
              'bin': {'uid': 2,'username': 'bin', 'shell':'/usr/sbin/nologin'},
              'nsa': {'uid': 1000,'username': 'nsa', 'shell': '/bin/bash'}}

for value in currentuser.values():
    print(f"{value['uid']:>8} {value['username']:<12} {value['shell']:<15}")
This will print:

Output:
0 root /bin/bash 1 daemon /usr/sbin/nologin 2 bin /usr/sbin/nologin 1000 nsa /bin/bash
I personally like this type of display better than separated with |. However, if you prefer that you can add these into f-string quite easily:

for value in currentuser.values():
    print(f"| {value['uid']:>8} | {value['username']:<12} | {value['shell']:<15}")
This will deliver:

Output:
| 0 | root | /bin/bash | 1 | daemon | /usr/sbin/nologin | 2 | bin | /usr/sbin/nologin | 1000 | nsa | /bin/bash
Another possibility
currentuser ={'root':{'uid': 0,'username': 'root' ,'shell': '/bin/bash'},
'daemon': {'uid': 1,'username': 'daemon' ,'shell': '/usr/sbin/nologin'},
'bin': {'uid': 2,'username': 'bin', 'shell':'/usr/sbin/nologin'},
'nsa': {'uid': 1000,'username': 'nsa', 'shell': '/bin/bash'}}

for v in currentuser.values():
    print(f'|{v["uid"]}{" ".rjust(10-len(str(v["uid"])))}|{v["username"]}{" ".rjust(10-len(v["username"]))}|{v["shell"]}')
Output:
|0 |root |/bin/bash |1 |daemon |/usr/sbin/nologin |2 |bin |/usr/sbin/nologin |1000 |nsa |/bin/bash
(May-03-2021, 07:50 AM)perfringo Wrote: [ -> ]You can pass formatting with f-strings so little adjustment to menator01 code would deliver required result (numbers are aligned to right and text to left which is canonical way to display these datatypes in table style):

currentuser ={'root':{'uid': 0,'username': 'root' ,'shell': '/bin/bash'},
              'daemon': {'uid': 1,'username': 'daemon' ,'shell': '/usr/sbin/nologin'},
              'bin': {'uid': 2,'username': 'bin', 'shell':'/usr/sbin/nologin'},
              'nsa': {'uid': 1000,'username': 'nsa', 'shell': '/bin/bash'}}

for value in currentuser.values():
    print(f"{value['uid']:>8} {value['username']:<12} {value['shell']:<15}")
This will print:

Output:
0 root /bin/bash 1 daemon /usr/sbin/nologin 2 bin /usr/sbin/nologin 1000 nsa /bin/bash
I personally like this type of display better than separated with |. However, if you prefer that you can add these into f-string quite easily:

for value in currentuser.values():
    print(f"| {value['uid']:>8} | {value['username']:<12} | {value['shell']:<15}")
This will deliver:

Output:
| 0 | root | /bin/bash | 1 | daemon | /usr/sbin/nologin | 2 | bin | /usr/sbin/nologin | 1000 | nsa | /bin/bash

Thank you this worked well!
Thank you all for your replies, the output is as i wanted it to print out.