Say I have the following HTML script:
<head>$name</head>
And I have the following shell script which replaces the variable in the HTML script with a name
#/bin/bash
report=$(cat ./a.html)
export name=$(echo aakash)
bash -c "echo \"$report\""
This works.
Now I have to implement the shell script in Python so that I am able to replace the variables in the HTML file and output the replaced contents in a new file. How do I do it?
An example would help. Thanks.
It looks like you're after a templating engine, but if you wanted a straight forward, no thrills, built into the standard library, here's an example using string.Template:
from string import Template
with open('a.html') as fin:
template = Template(fin.read())
print template.substitute(name='Bob')
# <head>Bob</head>
I thoroughly recommend you read the docs especially regarding escaping identifier names and using safe_substitute and such...
with open('a.html', 'r') as report:
data = report.read()
data = data.replace('$name', 'aakash')
with open('out.html', 'w') as newf:
newf.write(data)
Firstly you could save your html template like:
from string import Template
with open('a.html') as fin:
template = Template(fin.read())
Then if you want to substitute variables one at a time, you need to use safe_substitute and cast the result to a template every time. This wont return a key error even when a key value is not specified.
Something like:
new=Template(template.safe_substitute(name="Bob"))
After this , the new template is new , which needs to be modified again if you would want.
Related
I really can not figure how to do this.
I am trying to create a snippet that will read a file (the name I will get it by selecting it so it will be in the ${VISUAL}) and then using grep extract a line from it.
What I tried is something like
!v cat ${VISUAL} | grep "some text"
but of course that in shell ${VISUAL} has a different value.
I tried something in python, but I am lost. All I could get was
!p snip.rv=snip.v.text
that will give me the value for ${VISUAL}
Thank you for your help.
Maybe for your specific case you could use the vim builtin :read function ?
It's not quite grep, but if you're okay with Python-style regex, you can do this:
`!p
import re
from pathlib import Path
path = Path(snip.v.text)
content = path.read_text()
snip.rv = '\n'.join(re.findall(r'foo.*bar', content))
`
Having an odd problem.
I have a Django app that opens a file (represented as a Django FieldFile) and reads each row using readline() as below:
with file.open(mode='r') as f:
row = f.readline()
# do something with row...
The file is text, utf-8 encoded and lines are terminated with \r\n.
The problem is each row is being read as the hex representation of the string, so instead of "Hello" I get "48656c6c6f".
A few stranger things:
It previously worked properly, but at some point an update has broken it (I've tried rolling back to previous commits and it is still wonky, so possibly a dependency has updated and not something from my requirements.txt). Missed it in my testing because it is in a very rarely used part of the app.
If I read the same file using readlines() instead of readline() I see the correct string representation of the file wrapped in [b'...']
The file reads normally if I do it using straight Python open() and readline() from an interpreter
Forcing text mode with mode='rt' doesn't change the behaviour, neither does mode='rb'
The file is stored in a Minio bucket, so the defaut storage is storages.backends.s3boto3.S3Boto3Storage from django-storages and not the default Django storage class. This means that boto3, botocore and s3fs are also in the mix, making it more confusing for me to debug.
Scratching my head at why this worked before and what I'm doing wrong.
Environment is Python 3.8, Django 2.2.8 and 3.0 (same result) running in Docker containers.
EDIT
Let me point out that the fix for this is simply using
row = f.readline().decode()
but I would still like to figure out what's happening.
EDIT 2
Further to this, FieldFile.open() is reading the file as a binary file, whereas plain Python open() is reading the file as a text file.
This seems very weird.
I think you will see the solution immediately after trying following (I will then update my answer or delete it if it really doesn't help to find it, but I'm quite confident)
A assume, that there is some code, that is monkeypatching file.open or the django view function.
What I suggest is:
Start your code with manage.py runserver
Ad following code to manage.py (as the very first lines)
import file
print("ID of file.open at manage startup is", id(file.open)
Then add code to your view directly one line above the file.open
print("ID of file.open before opening is", id(file.open)
If both ids are different, then something monkeypatched your open function.
If both are the same, then the problem must be somewhere else.
If you don not see the output of these two prints, something might have monkeypatched your view.
If this doesn't work, then try to use
open() instead of file.open()
Is there any particular reason you use file.open()
Addendum 1:
So what you sai is, that file is an object instance of a class is it a FileField?
In any case can you obtain the name of the file and open it with a normal open() to see whether it is only file.open() that does funny things or whether it is also open() reading it this stange way.
Did you just open the file from command line with cat filename (or if under windows with type filename?
If that doesn't work we could add traces to follow each line of the source code that is being executed.
Addendum 2:
Well if you can't try this in a manage.py runserver, what happens if you try to read the file with a manage.py shell?
Just open the shell and type something like:
from <your_application>.models import <YourModel>
entry = <YourModel>.objects.get(id=<idofentry>)
line1 = entry.<filefieldname>.open("r").read().split("\n")[0]
print("line1 = %r" % line1)
If this is still not conclusive, (but only if you can reproduce the issue with the management shell, then create a small file containing the lines.
from <your_application>.models import <YourModel>
entry = <YourModel>.objects.get(id=<idofentry>)
import pdb; pdb.set_trace()
line1 = entry.<filefieldname>.open("r").read().split("\n")[0]
print("line1 = %r" % line1)
And import it from the management shell.
The code should enter the debugger and now you can single step through the open function and see whether you end up on sime weird function in some monkeypatch.
I have a little homework webpage. I'm trying to automate the production of the webpage each week.
I know very little about this. Wednesday I asked about importing Python functions that I made. I think I have grasped the concept. I've tested everything in Idle. All the modules work.
In my Python shell, (I use Idle in Ubuntu), everything does what I want.
I first append the paths:
for i in range(0, len(pyPaths)):
sys.path.append(pyPaths[i])
then import the modules:
from makeRBsInlineV1 import makeHTMLrbsNums
from makeCheckboxesInlineV1 import makeHTMLCBs
from makeDropdownboxesInlineV1 import makeDropdownboxes
from createhtmlTableInlineV1 import makeHTMLtable
from makeRBsInlineV2 import makeHTML_RBs
from readLinesTextboxesInlineV1 import readLinesmakeTBs
from makeThankyouPHPInlineV1 import makeThankyouPHP
All these modules return a text string which is a mixture of html tags + my text. It displays nicely in Firefox.
In Idle I just write, for example:
myString = readLinesTextboxesInlineV3()
it asks me a few questions and off it goes. Afterwards, myString is ready to be put in the webpage text string.
However, in bash, I cannot write
myString = readLinesTextboxesInlineV3()
in bash, I cannot write
myString = input('Enter the name of the module you want. ')
and then enter,
readLinesTextboxesInlineV3()
because then myString is just the input text, not the function.
Each week things are different, I may need to run 2 or more of the modules, add the result strings, then write them in the webpage text string at the correct place.
I run this in a
while True:
loop, so I can add strings from various modules.
For any given week, I don't know which module I want to use, so I make them all available.
I have a list of all the modules:
pyFiles = ['makeCheckboxesInlineV1()', 'dropdownboxesInlineV1()',
'createhtmlTableInlineV1()', 'makeRBsInlineV2()',
'readLinesTextboxesInlineV3()', 'makeThankyouPHPInlineV1()']
How do I assign myString to any 1 of the modules above when I run makeWebpage.py in bash?
I tried this:
pyFiles = [makeHTMLCBs(), makeDropdownboxes(), makeHTMLtable(), makeHTML_RBs(), readLinesmakeTBs(), makeThankyouPHP()]
Declare a list of the functions. Trouble is, as soon as I do that, Python wants to run the first function immediately. I was hoping I could enter a number and run say:
myString = pyFiles[3]
The best solution for you is to add arguments to your python script that can be added as flag to your command line.
This way you could call your script like the following from the shell (example):
python makeWebpage.py --module "makeCheckboxesInlineV1"
Python standard library provide argparse module for that specific need. It's really easy to handle and transform shell argument into python variable.
I recommend that you read that blog post which I found myself really useful. The part you need the most is What about argparse?
Add something like this in your main:
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument('-m', '--module', action='store_true')
args = parser.parse_args()
module = args.module # The variable module now is a String containing "makeCheckboxesInlineV1"
I am new to python and programming. Starting to try few things for my project..
My problem is as below
p=subprocess.Popen(Some command which gives me output],stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
p.wait()
content=p.stdout.readlines()
for line in content:
filedata=line.lstrip().rstrip()
-----> I want this filedata output to open and save it to a file.
If i use print filedata it works and gives me exactly what i wanted but i donot want to print and wanted to use this data later.
Thanks in advance..
You can do that in following two ways.
Option one uses more traditional way of file handling, I have used with statement, using with statement you don't have to worry about closing the file
Option two, which makes use of pathlib module and this is new in version 3.4 (I recommend using this)
somefile.txt is the full file path in file system. I've also included documentation links and I highly recommend going through those.
OPTION ONE
p=subprocess.Popen(Some command which gives me output],stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
p.wait()
content=p.stdout.readlines()
for line in content:
filedata=line.lstrip().rstrip()
with open('somefile.txt', 'a') as file:
file.write(filedata + '\n')
Documentation for The with Statement
OPTION TWO - For Python 3.4 or above
import pathlib
p=subprocess.Popen(Some command which gives me output],stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
p.wait()
content=p.stdout.readlines()
for line in content:
filedata=line.lstrip().rstrip()
pathlib.Path('somefile.txt').write_text(filedata + '\n')
Documentation on Pathlib module
I was trying to write variables on an html file,
using the commands
index = open('/var/www/index.html','a')
index.write('...')
index.close()
The problems that I am facing are:
how to clear previous values from html file using python commands
how to move to next line on html using python ( '\n' is not working).
As L3viathan mentioned, 'w' is used for over-writing the file.
When you use 'a', you're appending to the existing file.
http://docs.python.org/2/tutorial/inputoutput.html#reading-and-writing-files