I have two CSVs, one where the profiles are stored with the profile name naming each line and I want it to be a key in a dict like so: profiles = {"profile1": ["item"]} so I could pull the list of each profile / row.
Example of the CSVs
profiles.csv
PROFILE_NAME,FIRST_NAME,LAST_NAME
Profile1,John,Doe
Profile2,Jane,Deere
instructions.csv
PROFILE_NAME,JOB,HOURS
Profile1,Mechanic,50
Profile2,Cook,65
Code I have tried for storing rows as lists:
def info():
file = "profiles.csv"
with open(file) as f:
reader = csv.DictReader(f)
profiles = {}
for row in reader:
name = row['PROFILE_NAME']
profiles[name] = [
row['FIRSTNAME'],
row['LASTNAME']
]
return profiles
I'm extracting values from a csv file and storing these in a list.
The problem I have is that unless there is an exact match the elements/strings don't get extracted. How would I go about a case insensitive list search in Django/Python?
def csv_upload_view(request):
print('file is being uploaded')
if request.method == 'POST':
csv_file_name = request.FILES.get('file')
csv_file = request.FILES.get('file')
obj = CSV.objects.create(file_name=csv_file)
result = []
with open(obj.file_name.path, 'r') as f:
f.readline()
reader = csv.reader(f)
#reader.__next__()
for row in reader:
data = str(row).strip().split(',')
result.append(data)
transaction_id = data[1]
product = data[2]
quantity = data[3]
customer = data[4]
date = parse_date(data[5])
try:
product_obj = Product.objects.get(name__iexact=product)
except Product.DoesNotExist:
product_obj = None
print(product_obj)
return HttpResponse()
Edit:
the original code that for some reason doesn't work for me contained the following iteration:
for row in reader:
data = "".join(row)
data = data.split(';')
data.pop()
which allows to work with extracted string elements per row. The way I adopted the code storing the elements in a list (results=[]) makes it impossible to access the elements via the product models with Django.
The above mentioned data extraction iteration was from a Macbook while I'm working with a Windows 11 (wsl2 Ubuntu2204), is this the reason that the Excel data needs to be treated differently?
Edit 2:
Ok, I just found this
If your export file is destined for use on a Macintosh, you should choose the second CSV option. This option results in a CSV file where each record (each line in the file) is terminated with a carriage return, as expected by the Mac
So I guess I need to create a csv file in Mac format to make the first iteration work. Is there a way to make both csv (Windows/Mac) be treated the same? Similar to the mentioned str(row).strip().lower().split(',') suggestion?
If what you're trying to do is simply search for a string case insensitive then all you gotta do is lower the case of your search and your query (or upper).
Here's a revised code
def csv_upload_view(request):
print('file is being uploaded')
if request.method == 'POST':
csv_file_name = request.FILES.get('file')
csv_file = request.FILES.get('file')
obj = CSV.objects.create(file_name=csv_file)
result = []
with open(obj.file_name.path, 'r') as f:
f.readline()
reader = csv.reader(f)
#reader.__next__()
for row in reader:
data = str(row).strip().lower().split(',')
result.append(data)
_, transaction_id, product, quantity, customer, date, *_ = data
date = parse_date(date)
try:
product_obj = Product.objects.get(name__iexact=product)
except Product.DoesNotExist:
product_obj = None
print(product_obj)
return HttpResponse()
Then when you're trying to store the data make sure to store it lowercase.
Also, do not split a csv file on ,. Instead use the Python's CSV library to open a csv file, since the data might contain ,. Make sure to change csv.QUOTE so that it encapsulates everything with ".
I'm new to Python so excuse me if my question is kind of dumb.
I send some data into a csv file (I'm making a password manager). So I send this to this file (in this order), the name of the site, the e-mail corresponding and finally the password.
But I would like to print all the names already written in the csv file but here is my problem, for the first row it does print the whole row but for the following rows it works just well.
Here is my code, I hope u can help me with this.
csv_file = csv.reader(open('mycsvfile.csv', 'r'), delimiter=';')
try :
print("Here are all the sites you saved :")
for row in csv_file :
print(row[0])
except :
print("Nothing already saved")
Maybe it can help, but here is how I wrote my data into the csv file:
#I encrypt the email and the password thanks to fernet and an already written key
#I also make sure that the email is valid
file = open('key.key', 'rb')
key = file.read()
file.close()
f = Fernet(key)
website = input("web site name : \n")
restart = True
while restart :
mail = input("Mail:\n")
a = isvalidEmail(mail)
if a == True :
print("e-mail validated")
restart = False
else :
print("Wrong e-mail")
pws = input("password :\n")
psw_bytes = psw.encode()
mail_bytes = mail.encode()
psw_encrypted_in_bytes = f.encrypt(psw_bytes)
mail_encrypted_in_bytes = f.encrypt(mail_bytes)
mail_encrypted_str = mail_encrypted_in_bytes.decode()
psw_encrypted_str = psw_encrypted_in_bytes.decode()
f = open('a.csv', 'a', newline='')
tup1 = (website, mail_encrypted_str, psw_encrypted_str)
writer = csv.writer(f, delimiter = ';')
writer.writerow(tup1)
print("Saved ;)")
f.close()
return
And here is my output (I have already saved data)
Output (First, you see the name of the ws with the email and the psw encrypted then just the name which is what I want
I finally succeed, instead of using a csv.Reader, i used a csv.DictReader and as all the names i'm looking for are on the same column, i juste have to use the title of the columns.
So here is the code :
with open('mycsv.csv', newline='') as csvfile:
data = csv.DictReader(csvfile)
print("Websites")
print("---------------------------------")
for row in data:
print(row['The_title_of_my_column'])
make list from csv.reader()
rows = [row for row in csv_file]
and now you can get element by identifier using rows as list of lists
rows[id1][id2]
The place where I put this code belongs to an import page.And here there is data in the data I want to import in .txt format, but this data contains the \n character.
if request.method == "POST":
txt_file = request.FILES['file']
if not txt_file .name.endswith('.txt'):
messages.info(request,'This is not a txt file')
data_set = csv_file.read().decode('latin-1')
io_string = io.StringIO(data_set)
next(io_string)
csv_reader = csv.reader(io_string, delimiter='\t',quotechar="|")
for column in csv_reader:
b = Module_Name(
user= request.user,
a = column[1],
b = column[2],
c = column[3],
d = column[4],
e = column[5],
f = column[6],
g = column[7],
h = column[8],
)
b.save()
messages.success(request,"Successfully Imported...")
return redirect("return:return_import")
This can be called the full version of my code. To explain, there is a \n character in the data that comes here as column[1]. This file is a .txt file from another export. And in this export column[1];
This is
a value
and my django localhost new-line character seen in unquoted field - do you need to open the file in universal-newline mode? gives a warning and aborts the import to the system.
the csv reader iterates over rows, not columns. So if you want to append the data from a given column together, you must iterate over all the rows first. For example:
import csv
from io import StringIO
io_string = "this is , r0 c1\r\na value, r1 c2\r\n"
io_string = StringIO(io_string)
rows = csv.reader(io_string)
column_0_data = []
for row in rows:
column_0_data.append(row[0])
print("".join(column_0_data))
the rest of your code looks iffy to me, but that is off topic.
I need read a csv file and fill the empty/null values in column "Phone and Email" based on the person's address and write to a new csv file. Ex: if a person "Jonas Kahnwald" doesn't have the phone number or an email address but has the same address as the person above or below, say "Hannah Kahnwald", then we should fill the empty/null values with those person's details.
I won't be able to use python pandas as the rest of the code/programs are purely based on python 2.7 (unfortunately), so I just need to write a function or a logic to capture this information alone.
Input format/table looks like below with empty cells (csv file):
FirstName,LastName,Phone,Email,Address
Hannah,Kahnwald,1457871452,hannkahn#gmail.com,145han street
Micheal,Kahnwald,6231897383,,145han street
Jonas,Kahnwald,,,145han street
Mikkel,Nielsen,4509213887,mikneil#yahoo.com,887neil ave
Magnus,Nielsen,,magnusneil#kyle.co,887neil ave
Ulrich,Nielsen,,,887neil ave
katharina,Nielsen,,,887neil ave
Elisabeth,Doppler,5439001211,elsisop#amaz.com,211elis park
Peter,Doppler,,,211elis park
bartosz,Tiedmannn,6263172828,tiedman#skype.com,828alex street
Alexander,washington,,,321notsame street
claudia,Tiedamann,,,828alex street
Output format should be like below:
Hannah,Kahnwald,1457871452,hannkahn#gmail.com,145han street
Micheal,Kahnwald,6231897383,hannkahn#gmail.com,145han street
Jonas,Kahnwald,1457871452,hannkahn#gmail.com,145han street
Mikkel,Nielsen,4509213887,mikneil#yahoo.com,887neil ave
Magnus,Nielsen,4509213887,magnusneil#kyle.co,887neil ave
Ulrich,Nielsen,4509213887,mikneil#yahoo.com,887neil ave
katharina,Nielsen,4509213887,mikneil#yahoo.com,887neil ave
Elisabeth,Doppler,5439001211,elsisop#amaz.com,211elis park
Peter,Doppler,5439001212,elsisop#amaz.com,211elis park
bartosz,Tiedmannn,6263172828,tiedman#skype.com,828alex street
Alexander,washington,,,321notsame street
claudia,Tiedamann,6263172828,tiedman#skype.com,828alex street
import csv,os
def get_info(file path):
data = []
with open(file, 'rb') as fin:
csv_reader = csv.reader(fin)
next(reader)
for each in csv_reader:
FirstName = each[0]
LN = each[1]
Phone = "some function or logic"
email = " some function or logic"
Address = each[4]
login = ""
logout = ""
data.append([FirstName,LN,Phone,email,Address,login,logout])
f.close()
return data
Here's a significantly updated version that attempts to fill in missing data from other entries in the file, but only if they have the same Address field. To make the searching faster it builds a dictionary for internal use called attr_dict which contains all the records with a particular address. It also uses namedtuples internally to make the code a little more readable.
Note that when retrieving missing information, it will use the data from the first entry it finds stored in this internal dictionary at the Address. In addition, I don't think the sample data you provided contains every possible case, so will need to do additional testing.
import csv
from collections import namedtuple
def get_info(file_path):
# Read data from file and convert to list of namedtuples, also create address
# dictionary to use to fill in missing information from others at same address.
with open(file_path, 'rb') as fin:
csv_reader = csv.reader(fin, skipinitialspace=True)
header = next(csv_reader)
Record = namedtuple('Record', header)
newheader = header + ['Login', 'Logout'] # Add names of new columns.
NewRecord = namedtuple('NewRecord', newheader)
addr_dict = {}
data = [newheader]
for rec in (Record._make(row) for row in csv_reader):
if rec.Email or rec.Phone: # Worth saving?
addr_dict.setdefault(rec.Address, []).append(rec) # Remember it.
login, logout = "", "" # Values for new columns.
data.append(NewRecord._make(rec + (login, logout)))
# Try to fill in missing data from any other records with same Address.
for i, row in enumerate(data[1:], 1):
if not (row.Phone and row.Email): # Info missing?
# Try to copy it from others at same address.
updated = False
for other in addr_dict.get(row.Address, []):
if not row.Phone and other.Phone:
row = row._replace(Phone=other.Phone)
updated = True
if not row.Email and other.Email:
row = row._replace(Email=other.Email)
updated = True
if row.Phone and row.Email: # Info now filled in?
break
if updated:
data[i] = row
return data
INPUT_FILE = 'null_cols.csv'
OUTPUT_FILE = 'fill_cols.csv'
data = get_info(INPUT_FILE)
with open(OUTPUT_FILE, 'wb') as fout:
writer = csv.DictWriter(fout, data[0]) # First elem has column names.
writer.writeheader()
for row in data[1:]:
writer.writerow(row._asdict())
print('Done')
Screenshot of results in Excel: