How to split input arguments in Python - python

I have the below code which expects 1 or more file names as arguments.
It works for one file but now the input arguments can be multiple files such as 1.json 2.json 3.json.
How can I handle this?
import sys
import os
import json
inFile = sys.argv[1]
print(inFile)
with open(inFile, 'r') as file:
try:
json_data = json.load(file)
except ValueError as e:
print "Invalid Json supplied:%s" % e
exit(1)
else:
print "json file ok"
print(json_data)

Since argv is a list (parsing the passed arg string is done for you), you can iterate over it, skipping argv[0] which is the program filename:
import json
import sys
for arg in sys.argv[1:]:
with open(arg, "r") as file:
try:
json_data = json.load(file)
print "json file ok"
print json_data
except ValueError as e:
print "Invalid JSON supplied: %s" % e
exit(1)
You may want to put this data into a list so you can do something with it in your program:
import json
import sys
data = []
for arg in sys.argv[1:]:
with open(arg, "r") as file:
try:
data.append(json.load(file))
except ValueError as e:
print "Invalid JSON supplied: %s" % e
exit(1)

Related

Adding data to JSON file

I am working with a RaspberryPi using python. I want to send the data from the temp sensor to a JSON file. However, I am not sure how to do this. I would really appreciate some guidance on this matter. Thank you!
Here is my code:
import grovepi
import math
from time import sleep
from grove_rgb_lcd import *
sensor = 4
blue = 0
white = 1
setRGB(0,255,0)
while True:
try:
[temp,humidity] = grovepi.dht(sensor,blue)
if math.isnan(temp) == False and math.isnan(humidity) == False:
print("temp = %.02f C humidity =%.02f%%"%(temp, humidity))
t = str(temp)
h = str(humidity)
setText("Temp:" + t + "C\n" + "Humidity :" + h + "%")
except (IOError, TypeError) as e:
print(str(e))
setText("")
except KeyboardInterrupt as e:
print(str(e))
setText("")
break
sleep(0.05)
You can use the json module for this, I have listed to functions below that show reading and writing to JSON files:
import json
def read_json(file_path:str) -> dict:
"""Takes in a json file path and returns it's contents"""
with open(file_path, "r") as json_file:
content = json.load(json_file)
return content
def store_json(data:dict, file_path:str):
"""Takes in a python dict and stores it as a .json file"""
with open(file_path, "w") as json_file:
json.dump(data, json_file)
Make sure you pass a dict to store_json(), or it will error out.
In your case I think you want:
data = {}
data["temp"] = t
data["humidity"] = h
store_json(data, "path/to/file.json")

Python: reading filename from command line argument

I am making a simple script that counts some values from a csv file generated from google forms.
The script is as follows:
import csv
import os.path
fileName=None
if __name__=="__main__":
try:
fileName=argv[1]
isFile(fileName)
pass
except Exception as e:
print("You must provide a valid filename as parameter")
raise
def isFile(fileName):
if(not os.path.isfile(fileName)):
raise ValueError("You must provide a valid filename as parameter")
print fileName
def readCsvAndCountPercentPerFormItemFromGoogleForms(fileName):
times={}
totalRows=0
with open(fileName,'r') as csvfile:
csvReader=csv.reader(csvfile);
for row in csvreader:
value=row[1]
if(value in times.values()):
times[value]+=1
else:
times[value]=1
totalRows+=1
return calculateDictionaryAsPercent(times,totalRows)
def calculateDictionaryAsPercent(times,totalRows):
if(totalRows==0):
raise ValueError("The file does not contain any rows")
for key,val in times.items():
times[key]=(val/totalRows)*100
return times
finalTimes=readCsvAndCountPercentPerFormItemFromGoogleForms(fileName)
print finalTimes
But I get the following error:
Traceback (most recent call last):
File "csv.py", line 1, in <module>
import csv
File "/home/pcmagas/Kwdikas/python/csv.py", line 54, in <module>
finalTimes=readCsvAndCountPercentPerFormItemFromGoogleForms(fileName)
File "/home/pcmagas/Kwdikas/python/csv.py", line 26, in readCsvAndCountPercentPerFormItemFromGoogleForms
with open(fileName,'r') as csvfile:
TypeError: coercing to Unicode: need string or buffer, NoneType found
The problem is that for some reason the variable fileName does not change value in:
if __name__=="__main__":
try:
fileName=argv[1]
isFile(fileName)
pass
except Exception as e:
print("You must provide a valid filename as parameter")
raise
The following piece of code was base ton the first answer found on Detect and print if no command line argument is provided
So can you offer me a solution because I do not write python too often, therefore I did the following script in order to learn it better.
Edit 1
The code has been reformated to this:
import csv
from sys import argv
import os.path
def isFile(fileName):
if(not os.path.isfile(fileName)):
raise ValueError("You must provide a valid filename as parameter")
def readCsvAndCountPercentPerFormItemFromGoogleForms(fileName):
times={}
totalRows=0
with open(fileName,'r') as csvfile:
csvReader=csv.reader(csvfile);
for row in csvreader:
value=row[1]
if(value in times.values()):
times[value]+=1
else:
times[value]=1
totalRows+=1
return calculateDictionaryAsPercent(times,totalRows)
def calculateDictionaryAsPercent(times,totalRows):
if(totalRows==0):
raise ValueError("The file does not contain any rows")
for key,val in times.items():
times[key]=(val/totalRows)*100
return times
fileName=None
if __name__=="__main__":
try:
fileName=argv[1]
print("Filename: ",fileName)
isFile(fileName)
pass
except Exception as e:
print("You must provide a valid filename as parameter")
raise
print("Filename: ",fileName)
finalTimes=readCsvAndCountPercentPerFormItemFromGoogleForms(fileName)
print finalTimes
Still the same error.
In the end as mentioned the script should be this one:
import csv
from sys import argv
import os.path
def readCsvAndCountPercentPerFormItemFromGoogleForms(fileName):
times={}
totalRows=0
with open(fileName,'r') as csvfile:
csvReader=csv.reader(csvfile);
for row in csvReader:
value=row[1]
if(value in times.values()):
times[value]+=1
else:
times[value]=1
totalRows+=1
return calculateDictionaryAsPercent(times,totalRows)
def calculateDictionaryAsPercent(times,totalRows):
if(totalRows==0):
raise ValueError("The file does not contain any rows")
for key,val in times.items():
times[key]=(val/totalRows)*100
return times
def isFile(fileName):
if(not os.path.isfile(fileName)):
raise ValueError("You must provide a valid filename as parameter")
fileName=None
if __name__=="__main__":
try:
fileName=argv[1]
isFile(fileName)
pass
except Exception as e:
print("You must provide a valid filename as parameter")
raise
finalTimes=readCsvAndCountPercentPerFormItemFromGoogleForms(fileName)
print finalTimes

Iterating the content of a text file in python

I have a text file named 'triple_response.txt' which contain the some text as :
(1,(db_name,string),DSP)
(1,(rel, id),2)
(2,(rel_name, string),DataSource)
(2,(tuple, id),201)
(2,(tuple, id),202)
(2,(tuple, id),203)
(201,(src_id,varchar),Pos201510070)
(201,(src_name,varchar),Postgres)
(201,(password,varchar),root)
(201,(host,varchar),localhost)
(201,(created_date,date),2015-10-07)
(201,(user_name,varchar),postgres)
(201,(src_type,varchar),Structured)
(201,(db_name,varchar),postgres)
(201,(port,numeric),None)
(202,(src_id,varchar),pos201510060)
(202,(src_name,varchar),Postgres)
(202,(password,varchar),root)
(202,(host,varchar),localhost)
(202,(created_date,date),2015-10-06)
(202,(user_name,varchar),postgres)
(202,(src_type,varchar),Structured)
(202,(db_name,varchar),DSP)
(202,(port,numeric),5432)
(203,(src_id,varchar),pos201510060)
(203,(src_name,varchar),Postgres)
(203,(password,varchar),root)
(203,(host,varchar),localhost)
(203,(created_date,date),2015-10-06)
(203,(user_name,varchar),postgres)
(203,(src_type,varchar),Structured)
(203,(db_name,varchar),maindb)
(203,(port,numeric),5432)
I am trying to convert these contents into JSON using a python script:
import re
import collections
import json, jsonpickle
def convertToJSON(File):
word_list=[]
row_list = []
try:
with open(File,'r') as f:
for word in f:
word_list.append(word)
with open(File,'r+') as f:
for row in f:
print row
row_list.append(row.split())
column_list = zip(*row_list)
except IOError:
print "Error in opening file.."
triple =""
for t in word_list:
triple+=t
tripleList = re.findall(r"\([^\(^\)]*\)",triple)
idList = re.split(r"\([^\(^\)]*\)",triple)
i =0
jsonDummy = []
jsonData = {}
for trip in tripleList:
nameAndType = re.split(r",|:",trip)
if(i==0):
key = re.compile("[^\w']|_").sub("",idList[i])
else:
try:
key = re.compile("[^\w']|_").sub("",idList[i].split("(")[1])
except IndexError:
pass
i = i+1
if(idList[i].find('(')!=-1):
try:
content = re.compile("[^\w']|_").sub("",idList[i].split(")")[0])
except IndexError:
pass
else:
content = re.compile("[^\w']|_").sub("",idList[i])
try:
trip = trip[1:-1]
tripKey = trip[1]
except IndexError:
tripKey = ''
name = re.compile("[^\w']").sub("",nameAndType[0])
try:
typeName = re.compile("[^\w']|_").sub("",nameAndType[1])
except IndexError:
typeName = 'String'
tripDict = dict()
value = dict()
value[name] = content
tripDict[key]=value
jsonDummy.append(tripDict)
for j in jsonDummy:
for k,v in j.iteritems():
jsonData.setdefault(k, []).append(v)
data = dict()
data['data'] = jsonData
obj = {}
obj=jsonpickle.encode(data, unpicklable=False)
return obj
pass
I am calling this function convertToJSON() within the same file as:
print convertToJSON("triple_response.txt")
I am getting the output as i expect like:
{"data": {"1": [{"db_name": "DSP"}, {"rel": "2"}], "201": [{"src_id": "Pos201510070"}, {"src_name": "Postgres"}, {"password": "root"}, {"host": "localhost"}, {"created_date": "20151007"}, {"user_name": "postgres"}, {"src_type": "Structured"}, {"db_name": "postgres"}, {"port": "None"}], "203": [{"src_id": "pos201510060"}, {"src_name": "Postgres"}, {"password": "root"}, {"host": "localhost"}, {"created_date": "20151006"}, {"user_name": "postgres"}, {"src_type": "Structured"}, {"db_name": "maindb"}, {"port": "5432"}], "2": [{"rel_name": "DataSource"}, {"tuple": "201"}, {"tuple": "202"}, {"tuple": "203"}], "202": [{"src_id": "pos201510060"}, {"src_name": "Postgres"}, {"password": "root"}, {"host": "localhost"}, {"created_date": "20151006"}, {"user_name": "postgres"}, {"src_type": "Structured"}, {"db_name": "DSP"}, {"port": "5432"}]}}
Now the problem which i am facing, which i am calling this from the outside the class as:
def extractConvertData(self):
triple_response = SPO(source, db_name, table_name, response)
try:
_triple_file = open('triple_response.txt','w+')
_triple_file.write(triple_response)
print "written data in file.."
with open('triple_response.txt','r+') as f:
for word in f:
print word
jsonData = convertToJSON(str('triple_response.txt'))
except IOError:
print "Not able to open a file"
print "Converted into JSON"
print jsonData
pass
The same code of convertToJSON() is not working...
It neither giving any output nor giving any error, it is not able to read the content from the 'triple_response.txt' file in the line.
with open('triple_response.txt','r+') as f:
for word in f:
print word
Any one can tell me solution to this problem..
_triple_file is never closed (except implicitly when you end the Python process, which is a terrible practice).
You can get platform-specific behavior when you have dangling filehandles like that (what is your platform? Unix? Windows?). Probably the write to _triple_file is not getting flushed.
So don't leave it dangling. Make sure to close it after you write it: (_triple_file.write(triple_response)). And in fact then assert that that file length is non-zero, using os.stat(), otherwise raise an Exception.
Also, you only have one big try...except clause to catch all errors, this is too much in one bite. Break it into two separate try...except clauses for writing _triple_file, and then reading it back. (Btw you might like to use tempfile library instead, to sidestep needing to know your intermediate file's pathname).
Something like the following untested pseudocode:
triple_response = SPO(source, db_name, table_name, response)
try:
_triple_file = open('triple_response.txt','w+')
_triple_file.write(triple_response)
_triple_file.close()
except IOError:
print "Not able to write intermediate JSON file"
raise
assert [suitable expression involving os.stat('triple_response.txt') to test size > 0 ], "Error: intermediate JSON file was empty"
try:
with open('triple_response.txt','r+') as f:
for word in f:
print word
jsonData = convertToJSON(str('triple_response.txt'))
except IOError:
print "Not able to read back intermediate JSON file"
#raise # if you want to reraise the exception
...

Python code to ignore errors

I have a code that stops running each time there is an error.
Is there a way to add a code to the script which will ignore all errors and keep running the script until completion?
Below is the code:
import sys
import tldextract
def main(argv):
in_file = argv[1]
f = open(in_file,'r')
urlList = f.readlines()
f.close()
destList = []
for i in urlList:
print i
str0 = i
for ch in ['\n','\r']:
if ch in str0:
str0 = str0.replace(ch,'')
str1 = str(tldextract.extract(str0))
str2 = i.replace('\n','') + str1.replace("ExtractResult",":")+'\n'
destList.append(str2)
f = open('destFile.txt','w')
for i in destList:
f.write(i)
f.close()
print "Completed successfully:"
if __name__== "__main__":
main(sys.argv)
Many thanks
You should always 'try' to open files. This way you can manage exceptions, if the file does not exist for example. Take a loot at Python Tutorial Exeption Handling
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except IOError as e:
print "I/O error({0}): {1}".format(e.errno, e.strerror)
except ValueError:
print "Could not convert data to an integer."
except:
print "Unexpected error:", sys.exc_info()[0]
raise
or
for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except IOError:
print 'cannot open', arg
else:
print arg, 'has', len(f.readlines()), 'lines'
f.close()
Do not(!) just 'pass' in the exception block. This will(!) make you fall on your face even harder.
Where ever your error(s) is happening you can wrap it in a try/except block
for i in loop:
try:
code goes here...
except:
pass

Unicode Decode Error in Python with files

so I'm having this trouble with the decode. I found it in other threads how to do it for simple strings, with the u'string'.encode. But I can't find a way to make it work with files.
Any help would be appreciated!
Here's the code.
text = file.read()
text.replace(txt.encode('utf-8'), novo_txt.encode('utf-8'))
file.seek(0) # rewind
file.write(text.encode('utf-8'))
and here's the whole code, should it help.
#!/usr/bin/env python
# coding: utf-8
"""
Script to helps on translate some code's methods from
portuguese to english.
"""
from multiprocessing import Pool
from mock import MagicMock
from goslate import Goslate
import fnmatch
import logging
import os
import re
import urllib2
_MAX_PEERS = 1
try:
os.remove('traducoes.log')
except OSError:
pass
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
handler = logging.FileHandler('traducoes.log')
logger.addHandler(handler)
def fileWalker(ext, dirname, names):
"""
Find the files with the correct extension
"""
pat = "*" + ext[0]
for f in names:
if fnmatch.fnmatch(f, pat):
ext[1].append(os.path.join(dirname, f))
def encontre_text(file):
"""
find on the string the works wich have '_' on it
"""
text = file.read().decode('utf-8')
return re.findall(r"\w+(?<=_)\w+", text)
#return re.findall(r"\"\w+\"", text)
def traduza_palavra(txt):
"""
Translate the word/phrase to english
"""
try:
# try connect with google
response = urllib2.urlopen('http://google.com', timeout=2)
pass
except urllib2.URLError as err:
print "No network connection "
exit(-1)
if txt[0] != '_':
txt = txt.replace('_', ' ')
txt = txt.replace('media'.decode('utf-8'), 'média'.decode('utf-8'))
gs = Goslate()
#txt = gs.translate(txt, 'en', gs.detect(txt))
txt = gs.translate(txt, 'en', 'pt-br') # garantindo idioma tupiniquim
txt = txt.replace(' en ', ' br ')
return txt.replace(' ', '_') # .lower()
def subistitua(file, txt, novo_txt):
"""
should rewrite the file with the new text in the future
"""
text = file.read()
text.replace(txt.encode('utf-8'), novo_txt.encode('utf-8'))
file.seek(0) # rewind
file.write(text.encode('utf-8'))
def magica(File):
"""
Thread Pool. Every single thread should play around here with
one element from list os files
"""
global _DONE
if _MAX_PEERS == 1: # inviavel em multithread
logger.info('\n---- File %s' % File)
with open(File, "r+") as file:
list_txt = encontre_text(file)
for txt in list_txt:
novo_txt = traduza_palavra(txt)
if txt != novo_txt:
logger.info('%s -> %s [%s]' % (txt, novo_txt, File))
subistitua(file, txt, novo_txt)
file.close()
print File.ljust(70) + '[OK]'.rjust(5)
if __name__ == '__main__':
try:
response = urllib2.urlopen('http://www.google.com.br', timeout=1)
except urllib2.URLError as err:
print "No network connection "
exit(-1)
root = './app'
ex = ".py"
files = []
os.path.walk(root, fileWalker, [ex, files])
print '%d files found to be translated' % len(files)
try:
if _MAX_PEERS > 1:
_pool = Pool(processes=_MAX_PEERS)
result = _pool.map_async(magica, files)
result.wait()
else:
result = MagicMock()
result.successful.return_value = False
for f in files:
pass
magica(f)
result.successful.return_value = True
except AssertionError, e:
print e
else:
pass
finally:
if result.successful():
print 'Translated all files'
else:
print 'Some files were not translated'
Thank you all for the help!
In Python 2, reading from files produces regular (byte) string objects, not unicode objects. There is no need to call .encode() on these; in fact, that'll only trigger an automatic decode to Unicode first, which can fail.
Rule of thumb: use a unicode sandwich. Whenever you read data, you decode to unicode at that stage. Use unicode values throughout your code. Whenever you write data, encode at that point. You can use io.open() to open file objects that encode and decode automatically for you.
That also means you can use unicode literals everywhere; for your regular expressions, for your string literals. So use:
def encontre_text(file):
text = file.read() # assume `io.open()` was used
return re.findall(ur"\w+(?<=_)\w+", text) # use a unicode pattern
and
def subistitua(file, txt, novo_txt):
text = file.read() # assume `io.open()` was used
text = text.replace(txt, novo_txt)
file.seek(0) # rewind
file.write(text)
as all string values in the program are already unicode, and
txt = txt.replace(u'media', u'média')
as u'..' unicode string literals don't need decoding anymore.

Categories

Resources