Using 'string.ljust' to try and hold a fixed width.......

J

John F Dutcher

I use code like the following to retrieve fields from a form:

recd = []
recd.append(string.ljust(form.getfirst("lname",' '),15))
recd.append(string.ljust(form.getfirst("fname",' '),15))
etc., etc.

The intent is to finish by assigning the list to a string that I would
write to disk: recstr = string.join(recd,'')

The spaces expected are 'NOT' being provided with 'string.ljust'....

If I simply print the field immediately as in:
print string.ljust(form.getfirst("lname",' '),15)

they are not present; they are not present when assigned to the list,
and, of course, they are not present in the final string.
Is there a way to do this....so I can have spaces 'held' in the
object I want to write to the file ??
Thanks.
 
F

Fredrik Lundh

John said:
The spaces expected are 'NOT' being provided with 'string.ljust'....

If I simply print the field immediately as in:
print string.ljust(form.getfirst("lname",' '),15)

they are not present; they are not present when assigned to the list,
and, of course, they are not present in the final string.

are you sure they're not there, or is the problem just that print
doesn't show them to you? try using "repr" or "len":
15

also note that ljust doesn't do anything if the input string is
longer than the field width:
20

</F>
 
F

Francis Avila

John F Dutcher wrote in message
I use code like the following to retrieve fields from a form:

recd = []
recd.append(string.ljust(form.getfirst("lname",' '),15))
recd.append(string.ljust(form.getfirst("fname",' '),15))
etc., etc.

The intent is to finish by assigning the list to a string that I would
write to disk: recstr = string.join(recd,'')

The spaces expected are 'NOT' being provided with 'string.ljust'....

If I simply print the field immediately as in:
print string.ljust(form.getfirst("lname",' '),15)

they are not present; they are not present when assigned to the list,
and, of course, they are not present in the final string.
Is there a way to do this....so I can have spaces 'held' in the
object I want to write to the file ??
Thanks.

What does form.getfirst do? (Also, unless you're using an ancient Python,
the strings objects themselves have ljust methods and you don't need the
string module.)

string.ljust will never truncate or modify a string, only extend it, so I
don't know what you mean by having spaces "held". If the length of the
string is shorter than 15, string.ljust will return another string of length
15 with spaces on the right. But if its longer, string.ljust will return
the string unchanged (i.e., still longer than 15 chars).

Since you're writing this stuff to disk, I presume you need fixed-width
strings, so you can reliably read things back? If so, you can't safely use
string.ljust to pad *unless* you know *with certainty* that all strings fed
to it are 15 chars or shorter (because string.ljust won't truncate). So why
not use struct.pack and struct.unpack instead of string.join? (At least,
use string.joinwords() if you won't use ''.join())

E.g.:
recd = []
recd.append(form.getfirst("lname",' ')) # 'Avila' ?
recd.append(form.getfirst("fname",' ')) # 'Francis' ?

struct.pack('15s15s', *recd) # 'Avila\x00\x00Francis'
struct.unpack('15s15s', 'Avila\x00\x00Francis') # -> ('Avila', 'Francis')

Of course, struct pads with nulls, not spaces, so you already enter upon the
nasty world of binary files. You could postprocess the struct.pack string
with ''.replace('\x00', ' '), but you'll have to strip trailing spaces when
you struct.unpack().

You could write your own fixed-width-string class/function:

def fixedwidth(string, width=15):
if len(string) > width:
return string[:width]
else:
return string.ljust(width)

There's a lot of repetition going on here, so you might want to think of
wrapping all this functionality up in a 'formFieldSerializer' class of some
sort.

If it's possible to change the structure of what you write to disk, there
are a number of much better alternatives. Depending upon how rich your data
structure is and whether you need to name your fields, you could use (in
ascending complexity) colon-separated fields (':'.join(L). Remember to
escape colons in L!), the csv module, the ConfigParser module, or XML of
some kind (only if absolutely necessary). There are many other modules in
the std library which do serialization of some kind, like MimeWriter, etc.,
which may be appropriate for what you're doing. You can even use the db
modules if you need simple database.
 
J

John F Dutcher

There seems to be a difference between using IDLE to test the code and using
the same code in my CGI script as follows: (I'm using Python 2.3.1)


In the IDLE command shell this works exactly as expected, that is
ending spaces are preserved when joined to the 'rec' string:

ten = 'xxxxxxxxxx'
recd = []
recd.append(string.ljust(ten,15))
recd.append(string.ljust(ten,15))
recd.append(string.ljust(ten,15))
rec = string.join(recd,'')
print rec -----------------> ending spaces preserved
*************************************************************

In my CGI script where I retrieve 'form' data nothing works..
The use of a string to receive the form field first, and
then appending to 'recd'...or appending to 'recd' directly, both fail
to preserve the spaces....(which are preserved very well in the
IDLE mode using a string literal to start with, rather than 'form' data).


recd = []
lname = string.ljust(form.getfirst("lname",' '),15)
fname = string.ljust(form.getfirst("fname",' '),15)

recd.append(lname)
recd.append(fname)

recstr = string.join(recd,'')
print recstr ------------------> no ending spaces
 
J

John F Dutcher

In the IDLE command shell this works exactly as expected, that is
ending spaces are preserved when joined to the 'rec' string:
(If I don't import and use 'string.ljust), and use just 'ljust' I get
a "Namerror'(Python 2.3.1)

ten = 'xxxxxxxxxx'
recd = []
recd.append(string.ljust(ten,15))
recd.append(string.ljust(ten,15))
recd.append(string.ljust(ten,15))
rec = string.join(recd,'')
print rec -----------------> ending spaces preserved
*************************************************************

In my CGI script where I retrieve 'form' data nothing works..
The use of a string to receive the form field first, and
then appending to 'recd'...or appending to 'recd' directly both fail
to preserve the spaces....(which are preserved very well in the
IDLE mode using a string literal to start with) rather than 'form'data.


recd = []
lname = string.ljust(form.getfirst("lname",' '),15)
fname = string.ljust(form.getfirst("fname",' '),15)

recd.append(lname)
recd.append(fname)

recstr = string.join(recd,'')
print recstr ------------------> no ending spaces for fields



Francis Avila said:
John F Dutcher wrote in message
I use code like the following to retrieve fields from a form:

recd = []
recd.append(string.ljust(form.getfirst("lname",' '),15))
recd.append(string.ljust(form.getfirst("fname",' '),15))
etc., etc.

The intent is to finish by assigning the list to a string that I would
write to disk: recstr = string.join(recd,'')

The spaces expected are 'NOT' being provided with 'string.ljust'....

If I simply print the field immediately as in:
print string.ljust(form.getfirst("lname",' '),15)

they are not present; they are not present when assigned to the list,
and, of course, they are not present in the final string.
Is there a way to do this....so I can have spaces 'held' in the
object I want to write to the file ??
Thanks.

What does form.getfirst do? (Also, unless you're using an ancient Python,
the strings objects themselves have ljust methods and you don't need the
string module.)

string.ljust will never truncate or modify a string, only extend it, so I
don't know what you mean by having spaces "held". If the length of the
string is shorter than 15, string.ljust will return another string of length
15 with spaces on the right. But if its longer, string.ljust will return
the string unchanged (i.e., still longer than 15 chars).

Since you're writing this stuff to disk, I presume you need fixed-width
strings, so you can reliably read things back? If so, you can't safely use
string.ljust to pad *unless* you know *with certainty* that all strings fed
to it are 15 chars or shorter (because string.ljust won't truncate). So why
not use struct.pack and struct.unpack instead of string.join? (At least,
use string.joinwords() if you won't use ''.join())

E.g.:
recd = []
recd.append(form.getfirst("lname",' ')) # 'Avila' ?
recd.append(form.getfirst("fname",' ')) # 'Francis' ?

struct.pack('15s15s', *recd) # 'Avila\x00\x00Francis'
struct.unpack('15s15s', 'Avila\x00\x00Francis') # -> ('Avila', 'Francis')

Of course, struct pads with nulls, not spaces, so you already enter upon the
nasty world of binary files. You could postprocess the struct.pack string
with ''.replace('\x00', ' '), but you'll have to strip trailing spaces when
you struct.unpack().

You could write your own fixed-width-string class/function:

def fixedwidth(string, width=15):
if len(string) > width:
return string[:width]
else:
return string.ljust(width)

There's a lot of repetition going on here, so you might want to think of
wrapping all this functionality up in a 'formFieldSerializer' class of some
sort.

If it's possible to change the structure of what you write to disk, there
are a number of much better alternatives. Depending upon how rich your data
structure is and whether you need to name your fields, you could use (in
ascending complexity) colon-separated fields (':'.join(L). Remember to
escape colons in L!), the csv module, the ConfigParser module, or XML of
some kind (only if absolutely necessary). There are many other modules in
the std library which do serialization of some kind, like MimeWriter, etc.,
which may be appropriate for what you're doing. You can even use the db
modules if you need simple database.
 
J

John F Dutcher

Last shot ... then I'll leave you alone...I tried your 'fixedwidth'
function.
Almost predictably....it worked perfectly in IDLE when coded as below:
It has no effect at all when employed in the CGI script however, (the
returned
values do not have trailing spaces) ??

IDLE code:
def fixedwidth(string, width=15):
if len(string) > width:
return string[:width]
else:
return string.ljust(width)
ten = 'xxxxxxxxxx'
recd = []
recd.append(fixedwidth(ten))
recd.append(fixedwidth(ten))
recd.append(fixedwidth(ten))
rec = string.join(recd,'')
print rec
#f.close()
sys.exit()

Same code placed in CGI.... BUT....the passed string came in from the
form...can't see why there should be any difference.

Francis Avila said:
John F Dutcher wrote in message
I use code like the following to retrieve fields from a form:

recd = []
recd.append(string.ljust(form.getfirst("lname",' '),15))
recd.append(string.ljust(form.getfirst("fname",' '),15))
etc., etc.

The intent is to finish by assigning the list to a string that I would
write to disk: recstr = string.join(recd,'')

The spaces expected are 'NOT' being provided with 'string.ljust'....

If I simply print the field immediately as in:
print string.ljust(form.getfirst("lname",' '),15)

they are not present; they are not present when assigned to the list,
and, of course, they are not present in the final string.
Is there a way to do this....so I can have spaces 'held' in the
object I want to write to the file ??
Thanks.

What does form.getfirst do? (Also, unless you're using an ancient Python,
the strings objects themselves have ljust methods and you don't need the
string module.)

string.ljust will never truncate or modify a string, only extend it, so I
don't know what you mean by having spaces "held". If the length of the
string is shorter than 15, string.ljust will return another string of length
15 with spaces on the right. But if its longer, string.ljust will return
the string unchanged (i.e., still longer than 15 chars).

Since you're writing this stuff to disk, I presume you need fixed-width
strings, so you can reliably read things back? If so, you can't safely use
string.ljust to pad *unless* you know *with certainty* that all strings fed
to it are 15 chars or shorter (because string.ljust won't truncate). So why
not use struct.pack and struct.unpack instead of string.join? (At least,
use string.joinwords() if you won't use ''.join())

E.g.:
recd = []
recd.append(form.getfirst("lname",' ')) # 'Avila' ?
recd.append(form.getfirst("fname",' ')) # 'Francis' ?

struct.pack('15s15s', *recd) # 'Avila\x00\x00Francis'
struct.unpack('15s15s', 'Avila\x00\x00Francis') # -> ('Avila', 'Francis')

Of course, struct pads with nulls, not spaces, so you already enter upon the
nasty world of binary files. You could postprocess the struct.pack string
with ''.replace('\x00', ' '), but you'll have to strip trailing spaces when
you struct.unpack().

You could write your own fixed-width-string class/function:

def fixedwidth(string, width=15):
if len(string) > width:
return string[:width]
else:
return string.ljust(width)

There's a lot of repetition going on here, so you might want to think of
wrapping all this functionality up in a 'formFieldSerializer' class of some
sort.

If it's possible to change the structure of what you write to disk, there
are a number of much better alternatives. Depending upon how rich your data
structure is and whether you need to name your fields, you could use (in
ascending complexity) colon-separated fields (':'.join(L). Remember to
escape colons in L!), the csv module, the ConfigParser module, or XML of
some kind (only if absolutely necessary). There are many other modules in
the std library which do serialization of some kind, like MimeWriter, etc.,
which may be appropriate for what you're doing. You can even use the db
modules if you need simple database.
 
P

Peter Otten

John said:
Last shot ... then I'll leave you alone...I tried your 'fixedwidth'
function.
Almost predictably....it worked perfectly in IDLE when coded as below:
It has no effect at all when employed in the CGI script however, (the
returned
values do not have trailing spaces) ??

I am now pretty sure that fixedwidth() or str.ljust() are *not* the problem
with your cgi script. Step back and look for something *completely*
different, e. g.:
- Is it an old file that you are checking for the extra spaces?
- Do you think that print writes to a file (it can, if you do:
print >> destfile, "sometext")?

If you cannot track down the bug yourself, shorten the cgi script as much as
you can and post it on c.l.py. Try to describe the problem you perceive and
make as few implicit assumptions as possible, i. e. "This is my script's
output cut and pasted" rather than "It does not do what I want".

Peter
 
F

Francis Avila

John F Dutcher wrote in message
<[email protected]>...

I have nothing to add to help you with your problem (aside from what Peter
already said), but just a tip:

(If I don't import and use 'string.ljust), and use just 'ljust' I get
a "Namerror'(Python 2.3.1)


You probably learned Python out of an old book, back when Python didn't have
string methods. What I mean is, don't use the string module (it's slated
for depreciation), but just use ljust as a method of your string:
''.join(['a','b','c']) 'abc'
'a'.ljust(5) 'a '
'1234'.isdigit() True
dir('')
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__',
'__ge__', '__getattribute__', '__getitem__', '__getnewargs__',
'__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__',
'__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__',
'__str__', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith',
'expandtabs', 'find', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower',
'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip',
'replace', 'rfind', 'rindex', 'rjust', 'rstrip', 'split', 'splitlines',
'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

I'm sure you recognise many of those methods? To learn more, try help('')
in an interactive session.
 
S

Steve Horsley

Peter said:
I am now pretty sure that fixedwidth() or str.ljust() are *not* the problem
with your cgi script. Step back and look for something *completely*
different, e. g.:

Or maybe your browser holding an old response in its cache. Try holding
the shift key down while you click refresh.

Just a thought.

Steve
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,170
Messages
2,570,925
Members
47,468
Latest member
Fannie44U3

Latest Threads

Top