Re: on slices, negative indices, which are the equivalent procedures?

2021-08-06 Thread Chris Angelico
On Sat, Aug 7, 2021 at 5:22 AM Boris Dorestand  wrote:
>
> Jach Feng  writes:
>
> >> > s = "Jack Brandom"
> >> > s[3 : -13 : -1]
> >> >> 'kcaJ'
> >> >> I have no idea how to replace that -13 with a positive index. Is it
> >> >> possible at all?
> > That's not possible because a positive index is relative to the leftmost 
> > item 0
>
> And the middle index is always exclusive, so we can't go to the left of
> 0 and remain positive.  Okay, I think that answers it.  It's not
> possible at all.
>

An absent index isn't the same as any specific positive value, so,
yeah, it's not possible to replace it with a positive index. It IS
possible to replace it with None.

>>> s = "Jack Brandom"
>>> s[3:None:-1]
'kcaJ'

You could implement equivalent logic in your function.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: on slices, negative indices, which are the equivalent procedures?

2021-08-06 Thread Boris Dorestand
Jach Feng  writes:

>> > s = "Jack Brandom" 
>> > s[3 : -13 : -1] 
>> >> 'kcaJ' 
>> >> I have no idea how to replace that -13 with a positive index. Is it 
>> >> possible at all? 
> That's not possible because a positive index is relative to the leftmost item > 0

And the middle index is always exclusive, so we can't go to the left of
0 and remain positive.  Okay, I think that answers it.  It's not
possible at all.

> Below is some rules of slice usage which I collected sometimes ago.
> -
> slice s[i:j:k]
>  The result is from start index i to stop index j (excluded) in step k 
> (default is 1).  i, j, k can be positive or negative. For example:  s = [1,  
> 2,  3,  4,  5]
> 1. Positive index is relative to the leftmost item (0), negative index is 
> relative to the rightmost item (-1). Note: out-of-range index is valid.
>s[-4:5] == s[1:5] == [2,3,4,5]  # index 5 is out-of-range
>s[4:-6:-1] == [5,4,3,2,1]  # index -6 is out-of-range
> 2. The default index of i and j (When index is omitted) was decided by the 
> sign of k. 
> For positive k, the start index is 0 (the leftmost item) and the stop 
> index is the one after the rightmost item.
>s[:3] == s[0:3] == [1,2,3]
>s[1:] == s[1:5] == [2,3,4,5]
>For negative k, the start index is -1 (the rightmost item) and the stop 
> index is one ahead of the leftmost item 
>s[:2:-1] == s[-1:2:-1] == [5,4]
>s[3::-1] == s[3:-6:-1] == [4,3,2,1]
> 3. The items pick-up order was decided by the sign of k. For positive k, the 
> direction is toward the right. For negative k, it is toward the left.
> s[1:4] == [2,3,4]
> s[3:0:-1] == [4,3,2]
> 4. Invalid slice will return an empty []
> s[2:0] == []

Thank you.  This helped a bit more.  So now I propose the following
simulation.  Can anyone simplify this?  Thanks!

--8<---cut here---start->8---
def mySlice(it, beg, end, step = 1):
  """Simulates Python slices."""
  if step is None: 
step = 1
  assert step != 0, "step = 0 not allowed"
  ret = []
  cur = beg
  if step > 0:
return mySlicePositiveStep(it, beg, end, step)
  else:
return mySliceNegativeStep(it, beg, end, step)

def mySliceNegativeStep(it, beg, end, step = -1):
  """Assume STEP is always negative.  The difference between positive
and neative step is that it reverts the orientation of the loop, but the
loop always begins at BEG, never at END.
  """
  ret = []
  if beg == None:
beg = -1
  if end == None:
end = -len(it) - 1
  if beg >= 0: # how to translate positive indices to negative ones
beg = -len(it) + beg
  if end >= 0:
end = -len(it) + end
  cur = beg # begin here
  while cur > end: # stop as soon as you arrive at END
ret.append(it[cur])
cur += step
  return ret

def mySlicePositiveStep(it, beg, end, step = 1):
  """Assume STEP is always positive.  But if BEG or END are
negative, we apply the equivalence rule BEG == LEN(IT) + BEG.  
For example, if BEG is -1 and LEN(IT) == 10, then BEG is
equivalent to 9 == 10 + -1.  (Similarly for END.)
  """
  ret = []
  if beg == None:
beg = 0
  if end == None:
end = len(it)
  if beg < 0:
beg = len(it) + beg
  if end < 0:
end = len(it) + end
  cur = beg
  while cur < end:
ret.append(it[cur])
cur += step
  return ret
--8<---cut here---end--->8---
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Ask for help on using re

2021-08-06 Thread jak

Il 06/08/2021 12:57, Jach Feng ha scritto:

jak 在 2021年8月6日 星期五下午4:10:05 [UTC+8] 的信中寫道:

Il 05/08/2021 11:40, Jach Feng ha scritto:

I want to distinguish between numbers with/without a dot attached:


text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n'
re.compile(r'ch \d{1,}[.]').findall(text)

['ch 1.', 'ch 23.']

re.compile(r'ch \d{1,}[^.]').findall(text)

['ch 23', 'ch 4 ', 'ch 56 ']

I can guess why the 'ch 23' appears in the second list. But how to get rid of 
it?

--Jach


import re
t = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n'
r = re.compile(r'(ch +\d+\.)|(ch +\d+)', re.M)

res = r.findall(t)

dot = [x[1] for x in res if x[1] != '']
udot = [x[0] for x in res if x[0] != '']

print(f"dot: {dot}")
print(f"undot: {udot}")

out:

dot: ['ch 4', 'ch 56']
undot: ['ch 1.', 'ch 23.']
r = re.compile(r'(ch +\d+\.)|(ch +\d+)', re.M)

That's an interest solution! Where the '|' operator in re.compile() was 
documented?

--Jach



I honestly can't tell you, I've been using it for over 30 years. In any
case you can find some traces of it in the "regular expressions quick
reference" on the site https://regex101.com (bottom right side).

--
https://mail.python.org/mailman/listinfo/python-list


Re: Ask for help on using re

2021-08-06 Thread Jon Ribbens via Python-list
On 2021-08-06, jak  wrote:
> Il 06/08/2021 16:17, jak ha scritto:
>> Il 06/08/2021 12:57, Jach Feng ha scritto:
>>> That's an interest solution! Where the '|' operator in re.compile() 
>>> was documented?
>> 
>> I honestly can't tell you, I've been using it for over 30 years. In any
>> case you can find some traces of it in the "regular expressions quick
>> reference" on the site https://regex101.com (bottom right side).
>
> ...if I'm not mistaken, the '|' it is part of normal regular
> expressions, so it is not a specific extension of the python libraries.
> Perhaps this is why you don't find any documentation on it.

The Python documentation fully describes the regular expression syntax
that the 're' module supports, including features that are widely
supported by different regular expression systems and also Python
extensions. '|' is documented here:
https://docs.python.org/3/library/re.html#index-13
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Ask for help on using re

2021-08-06 Thread Jach Feng
jak 在 2021年8月6日 星期五下午4:10:05 [UTC+8] 的信中寫道:
> Il 05/08/2021 11:40, Jach Feng ha scritto: 
> > I want to distinguish between numbers with/without a dot attached: 
> > 
>  text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' 
>  re.compile(r'ch \d{1,}[.]').findall(text) 
> > ['ch 1.', 'ch 23.'] 
>  re.compile(r'ch \d{1,}[^.]').findall(text) 
> > ['ch 23', 'ch 4 ', 'ch 56 '] 
> > 
> > I can guess why the 'ch 23' appears in the second list. But how to get rid 
> > of it? 
> > 
> > --Jach 
> >
> import re
> t = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n'
> r = re.compile(r'(ch +\d+\.)|(ch +\d+)', re.M) 
> 
> res = r.findall(t) 
> 
> dot = [x[1] for x in res if x[1] != ''] 
> udot = [x[0] for x in res if x[0] != ''] 
> 
> print(f"dot: {dot}") 
> print(f"undot: {udot}") 
> 
> out: 
> 
> dot: ['ch 4', 'ch 56'] 
> undot: ['ch 1.', 'ch 23.']
> r = re.compile(r'(ch +\d+\.)|(ch +\d+)', re.M) 
That's an interest solution! Where the '|' operator in re.compile() was 
documented?

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Ask for help on using re

2021-08-06 Thread jak

Il 06/08/2021 16:17, jak ha scritto:

Il 06/08/2021 12:57, Jach Feng ha scritto:

jak 在 2021年8月6日 星期五下午4:10:05 [UTC+8] 的信中寫道:

Il 05/08/2021 11:40, Jach Feng ha scritto:

I want to distinguish between numbers with/without a dot attached:


text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n'
re.compile(r'ch \d{1,}[.]').findall(text)

['ch 1.', 'ch 23.']

re.compile(r'ch \d{1,}[^.]').findall(text)

['ch 23', 'ch 4 ', 'ch 56 ']

I can guess why the 'ch 23' appears in the second list. But how to 
get rid of it?


--Jach


import re
t = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n'
r = re.compile(r'(ch +\d+\.)|(ch +\d+)', re.M)

res = r.findall(t)

dot = [x[1] for x in res if x[1] != '']
udot = [x[0] for x in res if x[0] != '']

print(f"dot: {dot}")
print(f"undot: {udot}")

out:

dot: ['ch 4', 'ch 56']
undot: ['ch 1.', 'ch 23.']
r = re.compile(r'(ch +\d+\.)|(ch +\d+)', re.M)
That's an interest solution! Where the '|' operator in re.compile() 
was documented?


--Jach



I honestly can't tell you, I've been using it for over 30 years. In any
case you can find some traces of it in the "regular expressions quick
reference" on the site https://regex101.com (bottom right side).


...if I'm not mistaken, the '|' it is part of normal regular
expressions, so it is not a specific extension of the python libraries.
Perhaps this is why you don't find any documentation on it.

--
https://mail.python.org/mailman/listinfo/python-list


Re: Ask for help on using re

2021-08-06 Thread Jach Feng
ast 在 2021年8月5日 星期四下午11:29:15 [UTC+8] 的信中寫道:
> Le 05/08/2021 à 17:11, ast a écrit :
> > Le 05/08/2021 à 11:40, Jach Feng a écrit : 
> >> I want to distinguish between numbers with/without a dot attached: 
> >> 
> > text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' 
> > re.compile(r'ch \d{1,}[.]').findall(text) 
> >> ['ch 1.', 'ch 23.'] 
> > re.compile(r'ch \d{1,}[^.]').findall(text) 
> >> ['ch 23', 'ch 4 ', 'ch 56 '] 
> >> 
> >> I can guess why the 'ch 23' appears in the second list. But how to get 
> >> rid of it? 
> >> 
> >> --Jach 
> >> 
> > 
> > >>> import re 
> > 
> > >>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n' 
> > 
> > >>> re.findall(r'ch \d+\.', text) 
> > ['ch 1.', 'ch 23.'] 
> > 
> > >>> re.findall(r'ch \d+(?!\.)', text) # (?!\.) for negated look ahead 
> > ['ch 2', 'ch 4', 'ch 56']
> import regex 
> 
> # regex is more powerful that re
> >>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n'
> >>> regex.findall(r'ch \d++(?!\.)', text) 
> 
> ['ch 4', 'ch 56'] 
> 
> ## ++ means "possessive", no backtrack is allowed
Can someone explain how the difference appear? I just can't figure it out:-(

>>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n'
>>> re.compile(r'ch \d+[^.]').findall(text)
['ch 23', 'ch 4 ', 'ch 56 ']
>>> re.compile(r'ch \d+[^.0-9]').findall(text)
['ch 4 ', 'ch 56 ']

--Jach
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Ask for help on using re

2021-08-06 Thread jak

Il 05/08/2021 11:40, Jach Feng ha scritto:

I want to distinguish between numbers with/without a dot attached:


text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n'
re.compile(r'ch \d{1,}[.]').findall(text)

['ch 1.', 'ch 23.']

re.compile(r'ch \d{1,}[^.]').findall(text)

['ch 23', 'ch 4 ', 'ch 56 ']

I can guess why the 'ch 23' appears in the second list. But how to get rid of 
it?

--Jach



import re

t = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n'
r = re.compile(r'(ch +\d+\.)|(ch +\d+)', re.M)

res = r.findall(t)

dot = [x[1] for x in res if x[1] != '']
udot = [x[0] for x in res if x[0] != '']

print(f"dot:   {dot}")
print(f"undot: {udot}")

out:

dot:   ['ch 4', 'ch 56']
undot: ['ch 1.', 'ch 23.']
--
https://mail.python.org/mailman/listinfo/python-list


Re: on slices, negative indices, which are the equivalent procedures?

2021-08-06 Thread Jach Feng
> > s = "Jack Brandom" 
> > s[3 : -13 : -1] 
> >> 'kcaJ' 
> >> I have no idea how to replace that -13 with a positive index. Is it 
> >> possible at all? 
That's not possible because a positive index is relative to the leftmost item 0

Below is some rules of slice usage which I collected sometimes ago.
-
slice s[i:j:k]
 The result is from start index i to stop index j (excluded) in step k 
(default is 1).  i, j, k can be positive or negative. For example:  s = [1,  2, 
 3,  4,  5]
1. Positive index is relative to the leftmost item (0), negative index is 
relative to the rightmost item (-1). Note: out-of-range index is valid.
   s[-4:5] == s[1:5] == [2,3,4,5]  # index 5 is out-of-range
   s[4:-6:-1] == [5,4,3,2,1]  # index -6 is out-of-range
2. The default index of i and j (When index is omitted) was decided by the sign 
of k. 
For positive k, the start index is 0 (the leftmost item) and the stop index 
is the one after the rightmost item.
   s[:3] == s[0:3] == [1,2,3]
   s[1:] == s[1:5] == [2,3,4,5]
   For negative k, the start index is -1 (the rightmost item) and the stop 
index is one ahead of the leftmost item 
   s[:2:-1] == s[-1:2:-1] == [5,4]
   s[3::-1] == s[3:-6:-1] == [4,3,2,1]
3. The items pick-up order was decided by the sign of k. For positive k, the 
direction is toward the right. For negative k, it is toward the left.
s[1:4] == [2,3,4]
s[3:0:-1] == [4,3,2]
4. Invalid slice will return an empty []
s[2:0] == []
-

--Jach

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: on slices, negative indices, which are the equivalent procedures?

2021-08-06 Thread Jack Brandom
"Michael F. Stemper"  writes:

> On 05/08/2021 12.35, Jack Brandom wrote:
>> The FAQ at
>>https://docs.python.org/3/faq/programming.html#what-s-a-negative-index
>> makes me think that I can always replace negative indices with
>> positive
>> ones --- even in slices, although the FAQ seems not to say anything
>> about slices.
>> With slices, it doesn't seem to always work.  For instance, I can
>> reverse a "Jack" this way:
>> 
> s = "Jack Brandom"
> s[3 : -13 : -1]
>> 'kcaJ'
>> I have no idea how to replace that -13 with a positive index.  Is it
>> possible at all?
>
> I don't think so, because the second number (in this case -13) is the
> index before which you stop.

So, can you write a procedure that implements these rules?  It seems
that I'd begin at position 3 (that's "k" which I save somewhere), then I
subtract 1 from 3, getting 2 (that's "c", which I save somewhere), then
I subtract 1 from 2, getting 1 (that's "a", ...), then I subtract 1 from
1, getting 0 (that's J, ...), so I got "kcaJ" but my counter is 0 not
-13, which was my stopping point.

So it doesn't work as I'm currently thinking --- and my attempt to write
a procedure would not work.  There must be a procedure that mimics this,
of course.  I haven't understood the rules enough yet.

> For example:
>
 s
> 'Jack Brandom'
 s[3:0:-1]
> 'kca'

Okay, so we begin at 3 (which is "k"), then we go towards the beginning
of the string because of step = -1.  This would work with my iteration
attempted above --- I'd subtract 1 from 3, then from 2, then from 1 and
I'd stop as soon as I reach 0, so I wouldn't collect the J, as desired.
(I could write, therefore, such procedure for this case.)

 s[3:1:-1]
> 'kc'

Okay.

> However, since you want to go through item 0 in the original string,
> you don't need a number there at all:
>
 s[3::-1]
> 'kcaJ'

Thanks for mentioning this.

> Or, it you want to be more explicit, you could separately grab the
> substring and then reverse it:
>
 s[:4][::-1]
> 'kcaJ'

This is interesting.  It's a way to break the problem into smaller
steps.  So [::-1] always reverses the iterable.

> Does any of this help?

It does.  Thank you.  But my main objective is to imitate the rules of
slicing so that I can understand it.  In other words, I'd like to write
myself a procedure --- say mySlice --- that takes an iterable and three
integers (say beg, end, step) and be able to produce precisely

  iterable[beg : end : step]

without using this syntax.  This would give me the feeling that I really
know how it works.  (Because I simulated it.)

Ignoring the type of the iterable for now, I could begin with something
like this:

--8<---cut here---start->8---
def mySlice(it, beg, end, step = 1):
  ret = []
  cur = beg
  if step > 0:
while cur < end:
  ret.append(it[cur])
  cur += 1
return ret
  if step < 0:
return "not sure yet"
--8<---cut here---end--->8---

>>> "Jack Brandom"[0:4:1]
'Jack'

>>> mySlice("Jack Brandom", 0, 4, 1)
['J', 'a', 'c', 'k']

That's the spirit.  I can say I know the behavior because I can imitate
it perfectly.  But there seems to be various combinations of positive
and negative in the indices that confuses my mind pretty easily.

I think I need to break this down into cases and understand all the
possible behaviors.  For now, I think I can say that if the step is
positive, then it goes from the first indice to the second.  (It moves
in that direction.)  If the step is negative, then it goes from the
first indice to the second but the second must be smaller than the
first.  (But I'm assuming here all indices are positive and only the
step can switch sign.)  (This thing is looking too confusing. I must be
missing some simple rule.)
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: on slices, negative indices, which are the equivalent procedures?

2021-08-06 Thread Michael F. Stemper

On 05/08/2021 12.35, Jack Brandom wrote:

The FAQ at

   https://docs.python.org/3/faq/programming.html#what-s-a-negative-index

makes me think that I can always replace negative indices with positive
ones --- even in slices, although the FAQ seems not to say anything
about slices.

With slices, it doesn't seem to always work.  For instance, I can
reverse a "Jack" this way:


s = "Jack Brandom"
s[3 : -13 : -1]

'kcaJ'

I have no idea how to replace that -13 with a positive index.  Is it
possible at all?


I don't think so, because the second number (in this case -13) is the
index before which you stop. For example:

>>> s
'Jack Brandom'
>>> s[3:0:-1]
'kca'
>>> s[3:1:-1]
'kc'
>>>

However, since you want to go through item 0 in the original string,
you don't need a number there at all:

>>> s[3::-1]
'kcaJ'
>>>

Or, it you want to be more explicit, you could separately grab the
substring and then reverse it:

>>> s[:4][::-1]
'kcaJ'
>>>

Does any of this help?

--
Michael F. Stemper
If it isn't running programs and it isn't fusing atoms, it's just 
bending space.

--
https://mail.python.org/mailman/listinfo/python-list


on slices, negative indices, which are the equivalent procedures?

2021-08-06 Thread Jack Brandom
The FAQ at 

  https://docs.python.org/3/faq/programming.html#what-s-a-negative-index

makes me think that I can always replace negative indices with positive
ones --- even in slices, although the FAQ seems not to say anything
about slices.  

With slices, it doesn't seem to always work.  For instance, I can
reverse a "Jack" this way:

>>> s = "Jack Brandom"
>>> s[3 : -13 : -1]
'kcaJ'

I have no idea how to replace that -13 with a positive index.  Is it
possible at all?  

But this example gives me the idea that perhaps each slice is equivalent
to a certain loop (which I could write in a procedure).  So I'm looking
for these procedures.  If I can have the procedures in mind, I think I
will be able to undersand slices without getting surprised.

Do you have these procedures from the top of your mind?  While I haven't
given up yet, I am not getting too close.  Thank you!
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Ask for help on using re

2021-08-06 Thread ast

Le 06/08/2021 à 02:57, Jach Feng a écrit :

ast 在 2021年8月5日 星期四下午11:29:15 [UTC+8] 的信中寫道:

Le 05/08/2021 à 17:11, ast a écrit :

Le 05/08/2021 à 11:40, Jach Feng a écrit :



import regex

# regex is more powerful that re

text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n'
regex.findall(r'ch \d++(?!\.)', text)


['ch 4', 'ch 56']

## ++ means "possessive", no backtrack is allowed



Can someone explain how the difference appear? I just can't figure it out:-(



+, *, ? are greedy, means they try to catch as many characters
as possible. But if the whole match doesn't work, they release
some characters once at a time and try the whole match again.
That's backtrack.
With ++, backtrack is not allowed. This works with module regex
and it is not implemented in module re

with string = "ch 23." and pattern = r"ch \d+\."

At first trial \d+  catch 23
but whole match will fail because next character is . and . is not 
allowed (\.)


A backtrack happens:

\d+  catch only 2
and the whole match is successful because the next char 3 is not .
But this is not what we want.

with ++, no backtrack, so no match
"ch 23." is rejected
this is what we wanted


Using re only, the best way is probably

re.findall(r"ch \d+(?![.0-9])", text)
['ch 4', 'ch 56']
--
https://mail.python.org/mailman/listinfo/python-list


Re: Defining a Python enum in a C extension - am I doing this right?

2021-08-06 Thread Serhiy Storchaka
03.08.21 13:03, Bartosz Golaszewski пише:
> Just a follow-up: this is how I did it eventually:

I think it can be simpler.

1. No need to create the __main__ module. You can just create a dict. If
some attributes are required (e.g. __name__) it is easy to set them in
the Python code (__name__ = 'pycenum').

2. No need to import the enum module in the C code. It is easier to do
it in the Python code.

3. Can you define your DummyType in the Python code instead of the C
code? Even if you need to create in the C code, it may be better to
define your enum class inside a dummy DummyType. It will set correct
__qualname__ of the enum class:

__name__ = 'pycenum'
import enum
class DummyType:
class FooBar(enum.Enum):
...

4. Did you consider idea of making DummyType a heap-allocated type? It
may be easy to create new type with PyType_FromModuleAndSpec(), and it
is more stable API, and the type is not immutable, so it is easy to add
new attributes with PyObject_SetAttrString().

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Flask – how to write csv file & save using prefilled value of the filename (response.headers["Content-Disposition"]="attachment; filename=xxx")

2021-08-06 Thread MRAB

On 2021-08-06 16:50, Suretha Weweje wrote:

I am trying to upload a CSV file with flask, read and process one line at a
time while iterating through all rows of the file and write the results
back to a new CSV file.  My python script produces the correct results on
its own, but I am not able to get the same results when using Flask. I am
new to flask.


[snip]
>

 csv_reader = csv.reader(new)


[snip]


 *mywriter = csv.DictWriter('results.csv', fieldnames=headers_new)*

[snip]

The problem has nothing to do with Flask.

'csv.reader' and 'csv.DictWriter' expect a file object, but you're 
passing them strings.

--
https://mail.python.org/mailman/listinfo/python-list


Flask – how to write csv file & save using prefilled value of the filename (response.headers["Content-Disposition"]="attachment; filename=xxx")

2021-08-06 Thread Suretha Weweje
I am trying to upload a CSV file with flask, read and process one line at a
time while iterating through all rows of the file and write the results
back to a new CSV file.  My python script produces the correct results on
its own, but I am not able to get the same results when using Flask. I am
new to flask.


The CSV file that I want to work on has different row lengths and each row
contains the pair of column names(headers) and cell values for that row.



***Short example of the CSV file content** I am trying to upload with flask*

3012,"COMPANY NAME",3015,"LIVE",3020,916301,3022,"LB45",

4000,"92001",4018,"FORM5",4022,"A",4025,2017,4030,"SMITH",4040,"ANN",4060,’C5,

4000,"92002",4018,"FORM5",4022,"A",4025,2017,4030,"BROWN",4040,"JOE",4075,89500,



***The expected results***

3012  3015 3020   3022   4000   4018
   4022 4025  4030  4040  4060
4075

COMP NAME  "LIVE"   916301   "LB45"




"92001"   "FORM5"  "A"   2017   "SMITH""ANN "
C5


"92002"   "FORM5"  "A"   2017   "BROWN" "JOE"
 89500





*** This is my code so far ***

from flask import Flask*, *make_response*, **request*

import io
import csv

*app *= Flask(__name__)

def transform(*text_file_contents*):
*output *= []
*strip *= []
*the_headers *= []
*headers_new *= []
*num_lines *=

*0 **new *= *text_file_contents*.replace(""*, *"")
*csv_reader *= csv.reader(*new*)

for *line *in *csv_reader*:
*dictionary *= str(*line*)
*strip*.append(*dictionary*)

for *row *in *strip*:
*it *= iter(*row*)
*res_dct *= dict(zip(*it**, **it*))
*output*.append(*res_dct*)

for *key *in *res_dct*:
*f_name *=
*key the_headers*.append(*f_name*)
*the_headers *= list(set(sorted(*the_headers*)))
*headers_new *= sorted(*the_headers*)

*mywriter = csv.DictWriter('results.csv', fieldnames=headers_new)*
*mywriter*.writeheader()

for *data *in *output*:
*mywriter*.writerow(*data*)
*num_lines *+=
*1 *return

*data *@*app*.route('/')
def form():
return """


Select File To Convert







"""

@*app*.route('/transform'*, *methods=["POST"])
def transform_file():
*f *= *request*.files['data_file']
if not *f*:
return "No file"

*stream *= io.StringIO(*f*.stream.read().decode("UTF8")*, *newline=None)
csv_input = csv.reader(*stream*)

*stream*.seek(*0*)
*result = transform(stream.read())*

*response *= make_response(*result*)
*response*.headers["Content-Disposition"] = "attachment;
filename=result.csv"
return

*response *if __name__ == "__main__":
*app*.run(debug=True)



***The following TypeError**:*  *argument 1 must have a "write" method *is
displayed noting these two problems:

- result = transform(stream.read()) and

- mywriter = csv.DictWriter('results.csv', fieldnames=headers_new)



I am not sure if the problem might be with mywriter because the original
Python script below work fine as

with open('results.csv', 'x', newline='') as new_file:

mywriter = csv.DictWriter(new_file, fieldnames=headers_new)

mywriter.writeheader()



 whereas in Flask I am not sure how to link data written using the function
to **response.headers["Content-Disposition"] = "attachment;
filename=result.csv"**
-- 
https://mail.python.org/mailman/listinfo/python-list