Pdf-latex with python script, custom python variables into latex output - python

I currently have the following code which works to produce a PDF output. Is there a better way of writing up the content for the PDF, other than done here? This is a basic pdf, but am hoping to include multiple variables in later versions. I have inserted variable x, defined before the PDF content, into the latex pdf. Many thanks for any advice you can give.
PDF Output - image
import os
import subprocess
x = 7
content = \
r'''\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[margin=1cm,landscape]{geometry}
\title{Spreadsheet}
\author{}
\date{}
\begin{document}''' + \
r'This is document version: ' + str(x) +\
r'\end{document}'
parser = argparse.ArgumentParser()
parser.add_argument('-c', '--course')
parser.add_argument('-t', '--title')
parser.add_argument('-n', '--name',)
parser.add_argument('-s', '--school', default='My U')
args = parser.parse_args()
with open('doc.tex','w') as f:
f.write(content%args.__dict__)
cmd = ['pdflatex', '-interaction', 'nonstopmode', 'doc.tex']
proc = subprocess.Popen(cmd)
proc.communicate()
retcode = proc.returncode
if not retcode == 0:
os.unlink('doc.pdf')
raise ValueError('Error {} executing command: {}'.format(retcode, ' '.join(cmd)))
os.unlink('doc.tex')
os.unlink('doc.log')```

As explained in this video, I think a better approach would be to export the variables from Python and save them into a .dat file using the following function.
def save_var_latex(key, value):
import csv
import os
dict_var = {}
file_path = os.path.join(os.getcwd(), "mydata.dat")
try:
with open(file_path, newline="") as file:
reader = csv.reader(file)
for row in reader:
dict_var[row[0]] = row[1]
except FileNotFoundError:
pass
dict_var[key] = value
with open(file_path, "w") as f:
for key in dict_var.keys():
f.write(f"{key},{dict_var[key]}\n")
Then you can call the above function and save all the variables into mydata.dat. For example, in Python, you could save a variable and call it document_version using the following line of code:
save_var_latex("document_version", 21)
In LaTeX (in the preamble of your main file), you just have to import the following packages:
% package to open file containing variables
\usepackage{datatool, filecontents}
\DTLsetseparator{,}% Set the separator between the columns.
% import data
\DTLloaddb[noheader, keys={thekey,thevalue}]{mydata}{../mydata.dat}
% Loads mydata.dat with column headers 'thekey' and 'thevalue'
\newcommand{\var}[1]{\DTLfetch{mydata}{thekey}{#1}{thevalue}}
Then in the body of your document just use the \var{} command to import the variable, as follows:
This is document version: \var{document_version}

Related

Applying python script to file

This is a simple ask but I can't find any information on how to do it: I have a python script that is designed to take in a text file of a specific format and perform functions on it--how do I pipe a test file into the python script such that it is recognized as input()? More specifically, the Python is derived from skeleton code I was given that looks like this:
def main():
N = int(input())
lst = [[int(i) for i in input().split()] for _ in range(N)]
intervals = solve(N, lst)
print_solution(intervals)
if __name__ == '__main__':
main()
I just need to understand how to, from the terminal, input one of my test files to this script (and see the print_solution output)
Use the fileinput module
input.txt
...input.txt contents
script.py
#!/usr/bin/python3
import fileinput
def main():
for line in fileinput.input():
print(line)
if __name__ == '__main__':
main()
pipe / input examples:
$ cat input.txt | ./script.py
...input.txt contents
$ ./script.py < input.txt
...input.txt contents
You can take absolute or relative path in your input() function and then open this path via open()
filename = input('Please input absolute filename: ')
with open(filename, 'r') as file:
# Do your stuff
Please let me know if I misunderstood your question.
You can either:
A) Use sys.stdin (import sys at the top of course)
or
B) Use the ArgumentParser (from argparse import ArgumentParser) and pass the file as an argument.
Assuming A it would look something like this:
python script.py < file.extension
Then in the script it would look like:
fData = []
for line in sys.stdin.readLines():
fData.append(line)
# manipulate fData
There are a number of ways to achieve what you want. This is what I came up with off the top of my head. It may not be the best / efficient way, but it should work. I do a lot of file I/O with python at work and this is one of the ways I've achieved it in the past.
Note: If you want to write the manipulated lines back to the file use the argparse library.
Edit:
from argparse import ArgumentParser
def parseInput():
parser = ArgumentParser(description = "Takes input file to read")
parser.add_argument('-f', type = str, default = None, required =
True, help = "File to perform I/O on")
args = parser.parse_args()
return args
def main():
args = parseInput()
fData = []
# perform rb
with open(args.f, 'r') as f:
for line in f.readlines():
fData.append(line)
# Perform data manipulations
# perform wb
with open(args.f, 'w') as f:
for line in fData:
f.write(line)
if __name__ == "__main__":
main()
Then on command line it would look like:
python yourScript.py -f fileToInput.extension

filter a Linux log file using Python

I want to filter a log file to keep all lines matching a certain pattern. I want to do this with Python.
Here's my first attempt:
#!/usr/bin/env python
from sys import argv
script, filename = argv
with open(filename) as f:
for line in f:
try:
e = line.index("some_term_I_want_to_match")
except:
pass
else:
print(line)
How can I improve this to:
save the result to a new file of similar name (i.e., a different extension)
use regex to make it more flexible/powerful.
(I'm just learning Python. This question is as much about learning Python as it is about accomplishing this particular result.)
OK, here's what I came up with so far... But how do you do the equivalent of prepending an r as in the following line
re.compile(r"\s*")
where the string is not a string literal, as in the next line?
re.compile(a_string_variable)
Other than that, I think this updated version does the job:
#!/usr/bin/env python
from sys import argv
import re
import os
import argparse #requires Python 2.7 or above
parser = argparse.ArgumentParser(description='filters a text file on the search phrase')
parser.add_argument('-s','--search', help='search phrase or keyword to match',required=True)
parser.add_argument('-f','--filename', help='input file name',required=True)
parser.add_argument('-v','--verbose', help='display output to the screen too', required=False, action="store_true")
args = parser.parse_args()
keyword = args.search
original_file = args.filename
verbose = args.verbose
base_file, ext = os.path.splitext(original_file)
new_file = base_file + ".filtered" + ext
regex_c = re.compile(keyword)
with open(original_file) as fi:
with open(new_file, 'w') as fo:
for line in fi:
result = regex_c.search(line)
if(result):
fo.write(line)
if(verbose):
print(line)
Can this be easily improved?
Well, you know, you have answered most of your questions yourself already :)
For regular expression matching use re module (the doc has pretty explanatory examples).
You already have made use open() function for opening a file. Use the same function for open files for writing, just provide a corresponding mode parameter ("w" or "a" combined with "+" if you need, see help(open) in the Python interactive shell). That's it.

Python not saving files to a different folder than where the python file is on Ubuntu 11.10

So I am pulling jpg's from a url. I am able to save the image files as long as they are being saved to the same folder the python file is in. As soon as I attempt to change the folder(seen here as the outpath) the image files do not get created. I imagine it has something to do with my outpath, but it seems to be fine when I am printing and watching it in the console.
Ubuntu 11.10 OS by the way. I'm a newbie with both linux and python, so it could easily be either. :)
If I were to print the sequence taken from the CSV file it would look like: [['Champ1', 'Subname1', 'imgurl1'],['Champ2', 'subname2', 'imgurl2'],['Champ3','subname3','imgurl3']...]
(It was scraped from a website)
import csv
from urlparse import urlsplit
from urllib2 import urlopen, build_opener
from urllib import urlretrieve
import webbrowser
import os
import sys
reader = csv.reader(open('champdata.csv', "rb"), delimiter = ",", skipinitialspace=True)
champInfo = []
for champs in reader:
champInfo.append(champs)
size = len(champInfo)
def GetImages(x, out_folder="/home/sean/Home/workspace/CP/images"):
b=1
size = len(champInfo)
print size
while b < size:
temp_imgurls = x.pop(b)
filename = os.path.basename(temp_imgurls[2])
print filename
outpath = os.path.join(out_folder, filename)
print outpath
u = urlopen(temp_imgurls[2])
localFile = open(outpath, 'wb')
localFile.write(u.read())
localFile.close()
b+=1
GetImages(champInfo)
I understand it's quite crude, but it does work, only if I'm not attempting to change the save path.
Try providing the complete image path everywhere
E:/../home/sean/Home/workspace/CD/images
def GetImages(x):
b=1
size = len(champInfo)
print size
while b < size:
temp_imgurls = x.pop(b)
filename = temp_imgurls[2]
u = urlopen(temp_imgurls[2])
localFile = open(filename, 'wb')
localFile.write(u.read())
localFile.close()
And this code will be save files in the same directory where script is.
Updated Answer:
I think the answer to your problem is just to add a check for the output directory existence, and create it if needed. ie, add:
if not os.path.exists(out_folder):
os.makedirs(out_folder)
to your existing code.
More generally , you could try something more like this:
import csv
from urllib2 import urlopen
import os
import sys
default_outfolder = "/home/sean/Home/workspace/CD/images"
# simple arg passing wihtout error checking
out_folder = sys.argv[1] if len(sys.argv) == 2 else default_outfolder
if not os.path.exists(out_folder):
os.makedirs(out_folder) # creates out_folder, including any required parent ones
else:
if not os.path.isdir(out_folder):
raise RuntimeError('output path must be a directory')
reader = csv.reader(open('champdata.csv', "rb"), delimiter = ",", skipinitialspace=True)
for champs in reader:
img_url = champs[2]
filename = os.path.basename(img_url)
outpath = os.path.join(out_folder, filename)
print 'Downloading %s to %s' % (img_url, outpath)
with open(outpath, 'wb') as f:
u = urlopen(img_url)
f.write(u.read())
The above code works for champdata.csv of the form stuff,more_stuff,http://www.somesite.com.au/path/to/image.png
but will need to be adapted if I have not understood the actual format of your incoming data.

how to open up a child process to tail the files present in a config file using python on a mac machine?

I am trying to tail the files in a config file using python on mac
I am able to get the values from the config file but not able to open up child processes for the same
a sample config file has
[section1]
host_prefix = true
timestamp_prefix = true
[section2]
host = localhost
port = 1463
pids = /var/run/harvester
[files]
apache.access = /var/log/apache2/access.log
apache.errors = /var/log/apache2/errors.log
mail = /var/log/mail.log
mysql.log = /var/log/mysql.log
I am opening up the config file and trying to get the filepaths and I need to tail them in new child processes in separate terminals
#! /bin/env python
import StringIO
import os
import re
from multiprocessing import Process
COMMENT_CHAR = '#'
OPTION_CHAR = '='
def parse_config(filename):
options = {}
f = open(filename)
for line in f:
if COMMENT_CHAR in line:
line, comment = line.split(COMMENT_CHAR, 1)
if OPTION_CHAR in line:
option, value = line.split(OPTION_CHAR, 1)
option = option.strip()
value = value.strip()
options[option] = value
f.close()
return options
try:
f = open("/etc/harvest.conf", 'r')
print 'found'
options = parse_config('/etc/harvest.conf')
print options.values()
os.system('tail -f options.values')
except:
try:
f = open("/usr/local/etc/harvest.conf", 'r')
print 'found'
options = parse_config('/usr/local/etc/harvest.conf')
print options.values()
os.system('tail -f options.values')
except IOError:
print 'cannot find file'
the above code gives me all the values from the config file that includes 'localhost','1463'
but I want only the paths from the file and need to tail them in separate child processes
Try ConfigParser. It can work with INI files.
use os.path.exists to check if a file exists
use ConfigParser to parse an ini-type config file

In Python how to add headers for a file after gzip before writing it

I am trying to open a javascript file, read it, gzip it and then write it back to another file.. able to do all that.. but how can set the "Content-Encoding : gzip" before writing the compressed content... here is the code:
import os, sys, mimetypes, zipfile, gzip, cStringIO
from optparse import OptionParser
def main():
parser = OptionParser(usage='usage: %prog [options] src_file destination_file')
parser.add_option('-x', '--expires', action='store_true', help='set far future expiry for all files')
(options, args) = parser.parse_args()
if len(args) != 2:
parser.error("incorrect number of arguments")
name = os.path.normpath(args[0])
des_file = os.path.normpath(args[1])
try:
s_file = open(name, 'r')
content = s_file.read()
compressed = cStringIO.StringIO()
gz = gzip.GzipFile(filename=name, mode='w', fileobj=compressed)
gz.write(content)
gz.close()
s_file.close()
o_file = open(des_file, 'w')
##
## BEFORE WRITING THE CONTENT INTO A FILE HOW WE ADD THE Content-Encoding
##
o_file.write(compressed.getvalue())
o_file.close()
except (IOError, os.error), why:
print 'Failed to read the file', filename, '\n Exception:', why
That is usually determined by whatever is serving the file. Your job is usually limited to setting the correct file name extension (.gz in this case) when you create the file and configuring the server properly.

Categories

Resources