using a list from subprocess output - python-3.x

I use subprocess and python3 in the following script:
import subprocess
proc = subprocess.Popen("fail2ban-client -d".split(' '), stdout=subprocess.PIPE)
out, err = proc.communicate()
out.decode('ascii')
print(out)
The output is the following:
['set', 'syslogsocket', 'auto']
['set', 'loglevel', 'INFO']
['set', 'logtarget', '/var/log/fail2ban.log']
['set', 'dbfile', '/var/lib/fail2ban/fail2ban.sqlite3']
['set', 'dbpurgeage', 86400]
...
My issue is all this output is not a list. This is just a really big string with new line.
I have tried to convert each line to a list with this command:
eval(out.decode('ascii').split('\n')[0])
But I don't think this is the good way.
So my question is how can I convert a string (which looks like a list) to a list.

Though people generally are afraid of using eval, it is the way to go if you need to convert text literals into data. Instead of splitting up your (potentially long) string, you can simply read off the first line like so:
import io
f = io.StringIO(out.decode('ascii'))
first_list = eval(f.readline())
second_list = eval(f.readline())

Related

Writing strings to a text file in python

I am generating some random strings in python using the following code:
import string
import random
import os
passphrases = []
pass_file = open("Passphrases2.txt","w")
os.chmod("Passphrases2.txt",0o777)
for _ in range(100):
st = "".join(random.choice(string.ascii_lowercase + string.ascii_uppercase + string.digits) for i in range(random.randint(8,16)))
passphrases.append(st)
print(st)
for p in passphrases:
pass_file.write("\n"%p)
I want these strings to be stored in a text file in the same directory as the python code.
When I execute this code, a file named Passphrases2.txt gets created but it is empty in the first execution.
When I execute the same code for the second time, the file gets updated with the strings that were generated during the first execution, then on running the third time, it gets updated with the strings generated in the second execution and so on. I am unable to figure out why this is happening.
You need to .close() file or use with statement.
This is including some optimizations:
import os
from random import choice, randint
import string
alphabet = string.ascii_lowercase + string.ascii_uppercase + string.digits
with open("Passphrases2.txt", "w") as pass_file:
for _ in range(1000):
st = "".join(choice(alphabet) for i in range(randint(8, 16)))
print(st)
pass_file.write(f"{st}\n")
os.chmod("Passphrases2.txt", 0o777)
import string
import random
import os
passphrases = []
for _ in range(100):
st = "".join(random.choice(string.ascii_lowercase + string.ascii_uppercase + string.digits) for i in range(random.randint(8,16)))
passphrases.append(st)
print(st)
with open("Passphrases2.txt","w") as pass_file:
for p in passphrases:
pass_file.write("%s\n" %p)
It's because you are missing pass_file.close() at the end to properly close the file handle after finishing to write. Without properly closing, the write to file was not fully flushed and saved. It's like you are typing something in Notepad but have not yet hit the save button.
Then on the 2nd run, pass_file = open("Passphrases2.txt","w"), reopening the file handle will close the previous handle; this will act like pass_file.close() for the previous run and thus you are seeing previous data on 2nd run and so on.
You may add pass_file.close() after the last for loop or use the Python with statement to ensure file handle open is being closed properly after it is done.
You need to close the file in the end 😀

Python equivalent to matlab's var = char(fread(fid,100,'char'))';

I need to read a binary file in python for which I have a Matlab code already. I'm converting line by line of matlab code to python but stuck at this place, where I'm reading text data from binary file but the output is not in readable text format. Looking for below Matlab's equivalaent code in python
tried struct module in python to unpack but the output string is not readable straight away into a list
Matlab code:
var = char(fread(fid,100,'char'))';
Python code that I tried:
tmp = f.read(100)
abc, = struct.unpack('100c',tmp)
But value of 'abc' is not regular text string, instead it is something like b'/val1 val2 val3 val4'
I need to get the val1, val2, val3, val4 as strings in to a list
I think using the numpy function fromfile does exactly what you want.
import numpy as np
data = np.fromfile(filename, dtype=np.uint8, count=100,sep='')
count tells how many bytes to read and the empty sep treats the file as binary. See the documentation for details.

How to print a long string in multiple lines in Python3

I recently came across python f-string. Let, there is a long line of string like
string = 'L4qrGFHK8eDA9Vy05gNH7inxfaVpPZH3i9pRdWScalA0pIGHKGqUEXejplKiYaCNizbiKH72LoQaoz1pQH9caDfAX5xtfQAZEri7QGkvxMAJWXsjPEPLQhTtTvvhDR1tMM9zX8Dd0l15bBW1Q3VQReOsbP5AQmMOK9GV0WYPZ015sg7tg8JKOs7hFJfD8bdpUQgWbGrxSdS95PnBTf4P2nTWWLrWzo3DQNyXHs29R6MZ92qqfPLGL8SSQNchWyo4V9NoHdAHDo5TdPf6VmNQaQAl9HKLVawTTg379plHr81YYEoojzstCSPh3jAy9W4dmjTLrBUxzA9tK5UlHKMGx7IYieNGfXBKTaCegdJOUubZPajkp0KY8OcpHxlaVFVdIPi58n6VH7evAomB'
I want to print this string like this:
L4qrGFHK8eDA9Vy05gNH7inxfaVpPZH3i9pRdWSc
alA0pIGHKGqUEXejplKiYaCNizbiKH72LoQaoz1p
QH9caDfAX5xtfQAZEri7QGkvxMAJWXsjPEPLQhTt
TvvhDR1tMM9zX8Dd0l15bBW1Q3VQReOsbP5AQmMO
K9GV0WYPZ015sg7tg8JKOs7hFJfD8bdpUQgWbGrx
SdS95PnBTf4P2nTWWLrWzo3DQNyXHs29R6MZ92qq
fPLGL8SSQNchWyo4V9NoHdAHDo5TdPf6VmNQaQAl
9HKLVawTTg379plHr81YYEoojzstCSPh3jAy9W4d
mjTLrBUxzA9tK5UlHKMGx7IYieNGfXBKTaCegdJO
UubZPajkp0KY8OcpHxlaVFVdIPi58n6VH7evAomB
And I want to use F-strings. I have tried left alignment like
print(f"{string}:<{40}")
But it is not working.
This is what you use textwrap for:
import textwrap
string = 'L4qrGFHK8eDA9Vy05gNH7inxfaVpPZH3i9pRdWScalA0pIGHKGqUEXejplKiYaCNizbiKH72LoQaoz1pQH9caDfAX5xtfQAZEri7QGkvxMAJWXsjPEPLQhTtTvvhDR1tMM9zX8Dd0l15bBW1Q3VQReOsbP5AQmMOK9GV0WYPZ015sg7tg8JKOs7hFJfD8bdpUQgWbGrxSdS95PnBTf4P2nTWWLrWzo3DQNyXHs29R6MZ92qqfPLGL8SSQNchWyo4V9NoHdAHDo5TdPf6VmNQaQAl9HKLVawTTg379plHr81YYEoojzstCSPh3jAy9W4dmjTLrBUxzA9tK5UlHKMGx7IYieNGfXBKTaCegdJOUubZPajkp0KY8OcpHxlaVFVdIPi58n6VH7evAomB'
# print("{string}:<40")
print(textwrap.fill(string, 40))
L4qrGFHK8eDA9Vy05gNH7inxfaVpPZH3i9pRdWSc
alA0pIGHKGqUEXejplKiYaCNizbiKH72LoQaoz1p
QH9caDfAX5xtfQAZEri7QGkvxMAJWXsjPEPLQhTt
TvvhDR1tMM9zX8Dd0l15bBW1Q3VQReOsbP5AQmMO
K9GV0WYPZ015sg7tg8JKOs7hFJfD8bdpUQgWbGrx
SdS95PnBTf4P2nTWWLrWzo3DQNyXHs29R6MZ92qq
fPLGL8SSQNchWyo4V9NoHdAHDo5TdPf6VmNQaQAl
9HKLVawTTg379plHr81YYEoojzstCSPh3jAy9W4d
mjTLrBUxzA9tK5UlHKMGx7IYieNGfXBKTaCegdJO
UubZPajkp0KY8OcpHxlaVFVdIPi58n6VH7evAomB

How to get the last, by the code, printed text Python

Let's say my code looks like:
print('Hello World')
result:
>>>Hello World
How can I retrieve what has been printed and put it in a string or in a list of strings if it's more than one print (for example by saying from where to where it should get them)
You can overload the print function, and do something along these lines:
import sys
last_out = ''
def print(message):
global last_out
last_out = message
sys.stdout.write(message+'\n')
print('derp')
print(last_out)
Output:
derp
derp
You could also save the message in an array, and retrieve the last x amount of strings for example

Basics on Empty List in Python

I am a newbie in Python, and I only have been programming in the language for the third day. I convert from Matlab because I am graduating from university and I just cannot afford the heavy cost of the software.
I am trying to add several filenames to a list, which fails. The following is my code:
import os
dirname = r"D:\MyFiles"
temp = os.listdir(dirname)
fl = []
for fn in temp:
if fn.startswith('L0116'):
fl = fl.append(fn)
What I don't understand is, the variable fl when initiated with [] returns as the list type, but then I fail to append the list with the above loop. I recheck my code using interactive prompt and I found out that the type changes to str and fails to append more.
I am stuck at this and I tried to google for about an hour without any clear clue to how I should do this.
Is there a better way? Or which part did I do it wrong?
Thank you so much for your help!
The append() method mutates the list in place. You should just append fn like this:
fl.append(fn)
don't try to assign the result of fl.append(fn) (which is None, by the way)
Also, don't use r"foo" strings for filenames. They are designed for use with regular expressions and using them for filenames or other kinds of strings will bite you. For example, you cannot end such a string with a backslash.
append works inplace, so no need to assign it to the list itself (fl = fl.append(fn)) just do fl.append(fn)
List comprehension:
import os
dirname = r"D:\MyFiles"
fl = [fn for fn in os.listdir(dirname) if fn.startswith('L0116')]
List append in python does not return a type, instead, you simply call the method like so:
import os
dirname = r"D:\MyFiles"
temp = os.listdir(dirname)
fl = []
for fn in temp:
if fn.startswith('L0116'):
fl.append(fn)
I haven't tested this code, but it should work. Your logic was resetting the list every time.

Resources