Re: [python] Rekurzivní generátor v Pythonu 3?

2016-08-31 Tema obsahu Matěj Cepl
On 2016-08-30, 10:28 GMT, Petr Messner wrote:
> To je veselé, když někdo dělá benchmark profilerem.

a) uznávám:

$ time python3 test_append.py 

real0m2.429s
user0m1.850s
sys 0m0.565s
$ time python3 test_plus.py 

real0m2.471s
user0m2.096s
sys 0m0.372s
$ time python3 test_plus.py 

  Na svoji obranu bych dodal, že ten rozdíl je fakt minimální, 
  a že se to opravdu v pythonu 2.5 změnilo.

b) je to úplně jedno, protože o rychlost v tomhle případě opravdu
   nejde. Nějaké nápady k té rekurzivitě? Dělal jste někdo něco
   takového?

Matěj

-- 
https://matej.ceplovi.cz/blog/, Jabber: mc...@ceplovi.cz
GPG Finger: 3C76 A027 CA45 AD70 98B5  BC1D 7920 5802 880B C9D8
 
The American Republic will endure, until politicians realize they
can bribe the people with their own money.
-- based on a statement of Alexander Fraser Tytler
___
Python mailing list
python@py.cz
http://www.py.cz/mailman/listinfo/python

Visit: http://www.py.cz


Re: [python] Rekurzivní generátor v Pythonu 3?

2016-08-30 Tema obsahu Ondrej Tuma
Zdravím vespolek,

kolega toto téma řešil tak před třemi lety a došel k závěru že je to
jedno. Resp. v každé verzi to bylo jinak. Pravda vstupovali do toho
i verze 2.x. Asi taky záleží jak moc jsou ty texty konstantní,
resp. jako moc jsou dynamické, v jakém kompilátoru s jakými přepínači je
pythoní interpretr kompilovaný a ad absurdum na jakém HW to běží.

Ondra

V Tue, 30 Aug 2016 12:28:30 +0200
Petr Messner  napsáno:

> To je veselé, když někdo dělá benchmark profilerem.
> 
> $ cat test_plus.py
> out = ''
> for i in range(1000):
> out += 'Nebudu komentovat rychlost algoritmů bez měření'
> $ cat test_append.py
> out = []
> for i in range(1000):
> out.append('Nebudu komentovat rychlost algoritmů bez měření')
> outstr = ''.join(out)
> $ time python3 test_plus.py
> 
> real 0m2.835s
> user 0m2.536s
> sys 0m0.288s
> $ time python3 test_append.py
> 
> real 0m1.848s
> user 0m1.588s
> sys 0m0.256s
> 
> 
> 
> Dne 30. srpna 2016 11:39 Matěj Cepl  napsal(a):
> 
> > On 2016-08-28, 10:54 GMT, Petr Messner wrote:
> > > Na tohle se vykašli. Jakmile dokument nemá stromovou
> > > strukturu, tak je vše tisíckrát složitější. Dikybohu toto XML
> > > neumí.
> >
> > Tohle je rada s odpuštěním na h... Ten vstupní datový formát mám
> > daný, s tím nemůžu nic dělat.
> >
> > > nedělej skládání řetězců stylem txt += part, je to strašně
> > > pomalé (O(n^2) místo O(n))..  Z txt si udělej list a používej
> > > append: txt.append(part) a na konci "".join(txt).
> >
> > To je veselé jak tyhle pověry drží. Tohle bylo opraveno
> > v pythonu 2.5 (pokud se nemýlím).
> >
> > ~$ cat test_plus.py
> > out = ''
> > for i in range(1000):
> > out += 'Nebudu komentovat rychlost algoritmů bez měření'
> > ~$ python3 -mcProfile test_plus.py
> >  3 function calls in 1.970 seconds
> >
> >Ordered by: standard name
> >
> >ncalls  tottime  percall  cumtime  percall
> > filename:lineno(function) 11.9701.9701.9701.970
> > test_plus.py:1() 10.0000.0001.9701.970
> > {built-in method exec} 10.0000.0000.0000.000
> > {method 'disable' of '_lsprof.Profiler' objects}
> >
> >
> > ~$ cat test_append.py
> > out = []
> > for i in range(1000):
> > out.append('Nebudu komentovat rychlost algoritmů bez
> > měření') outstr = ''.join(out)
> > ~$ python3 -mcProfile test_append.py
> >  1004 function calls in 3.331 seconds
> >
> >Ordered by: standard name
> >
> >ncalls  tottime  percall  cumtime  percall
> > filename:lineno(function) 11.8451.8453.3313.331
> > test_append.py:1()
> > 10.0000.0003.3313.331 {built-in method
> > exec} 10000.5280.0000.5280.000 {method 'append'
> > of 'list' objects}
> > 10.0000.0000.0000.000 {method 'disable'
> > of '_lsprof.Profiler' objects}
> > 10.9590.9590.9590.959 {method 'join' of
> > 'str' objects}
> >
> > ~$
> >
> > Hezký den,
> >
> > Matěj
> >
> > --
> > https://matej.ceplovi.cz/blog/, Jabber: mc...@ceplovi.cz
> > GPG Finger: 3C76 A027 CA45 AD70 98B5  BC1D 7920 5802 880B C9D8
> >
> > You either die a hero or you live long enough to see yourself
> > become the villain.
> >   -- Harvey Dent in The Dark Knight
> > ___
> > Python mailing list
> > python@py.cz
> > http://www.py.cz/mailman/listinfo/python
> >
> > Visit: http://www.py.cz
> >



-- 
Ondřej Tůma 
www: http://ipv6.mcbig.cz   jabber: mc...@jabber.cz   twitter: mcbig_cz


pgpMsU4ScB0A8.pgp
Description: OpenPGP digital signature
___
Python mailing list
python@py.cz
http://www.py.cz/mailman/listinfo/python

Visit: http://www.py.cz

Re: [python] Rekurzivní generátor v Pythonu 3?

2016-08-30 Tema obsahu Petr Messner
To je veselé, když někdo dělá benchmark profilerem.

$ cat test_plus.py
out = ''
for i in range(1000):
out += 'Nebudu komentovat rychlost algoritmů bez měření'
$ cat test_append.py
out = []
for i in range(1000):
out.append('Nebudu komentovat rychlost algoritmů bez měření')
outstr = ''.join(out)
$ time python3 test_plus.py

real 0m2.835s
user 0m2.536s
sys 0m0.288s
$ time python3 test_append.py

real 0m1.848s
user 0m1.588s
sys 0m0.256s



Dne 30. srpna 2016 11:39 Matěj Cepl  napsal(a):

> On 2016-08-28, 10:54 GMT, Petr Messner wrote:
> > Na tohle se vykašli. Jakmile dokument nemá stromovou
> > strukturu, tak je vše tisíckrát složitější. Dikybohu toto XML
> > neumí.
>
> Tohle je rada s odpuštěním na h... Ten vstupní datový formát mám
> daný, s tím nemůžu nic dělat.
>
> > nedělej skládání řetězců stylem txt += part, je to strašně
> > pomalé (O(n^2) místo O(n))..  Z txt si udělej list a používej
> > append: txt.append(part) a na konci "".join(txt).
>
> To je veselé jak tyhle pověry drží. Tohle bylo opraveno
> v pythonu 2.5 (pokud se nemýlím).
>
> ~$ cat test_plus.py
> out = ''
> for i in range(1000):
> out += 'Nebudu komentovat rychlost algoritmů bez měření'
> ~$ python3 -mcProfile test_plus.py
>  3 function calls in 1.970 seconds
>
>Ordered by: standard name
>
>ncalls  tottime  percall  cumtime  percall filename:lineno(function)
> 11.9701.9701.9701.970 test_plus.py:1()
> 10.0000.0001.9701.970 {built-in method exec}
> 10.0000.0000.0000.000 {method 'disable' of
> '_lsprof.Profiler' objects}
>
>
> ~$ cat test_append.py
> out = []
> for i in range(1000):
> out.append('Nebudu komentovat rychlost algoritmů bez měření')
> outstr = ''.join(out)
> ~$ python3 -mcProfile test_append.py
>  1004 function calls in 3.331 seconds
>
>Ordered by: standard name
>
>ncalls  tottime  percall  cumtime  percall filename:lineno(function)
> 11.8451.8453.3313.331
> test_append.py:1()
> 10.0000.0003.3313.331 {built-in method exec}
>  10000.5280.0000.5280.000 {method 'append' of
> 'list' objects}
> 10.0000.0000.0000.000 {method 'disable' of
> '_lsprof.Profiler' objects}
> 10.9590.9590.9590.959 {method 'join' of 'str'
> objects}
>
> ~$
>
> Hezký den,
>
> Matěj
>
> --
> https://matej.ceplovi.cz/blog/, Jabber: mc...@ceplovi.cz
> GPG Finger: 3C76 A027 CA45 AD70 98B5  BC1D 7920 5802 880B C9D8
>
> You either die a hero or you live long enough to see yourself become the
> villain.
>   -- Harvey Dent in The Dark Knight
> ___
> Python mailing list
> python@py.cz
> http://www.py.cz/mailman/listinfo/python
>
> Visit: http://www.py.cz
>
___
Python mailing list
python@py.cz
http://www.py.cz/mailman/listinfo/python

Visit: http://www.py.cz

Re: [python] Rekurzivní generátor v Pythonu 3?

2016-08-30 Tema obsahu Matěj Cepl
On 2016-08-28, 10:54 GMT, Petr Messner wrote:
> Na tohle se vykašli. Jakmile dokument nemá stromovou 
> strukturu, tak je vše tisíckrát složitější. Dikybohu toto XML 
> neumí. 

Tohle je rada s odpuštěním na h... Ten vstupní datový formát mám 
daný, s tím nemůžu nic dělat.

> nedělej skládání řetězců stylem txt += part, je to strašně 
> pomalé (O(n^2) místo O(n))..  Z txt si udělej list a používej 
> append: txt.append(part) a na konci "".join(txt).

To je veselé jak tyhle pověry drží. Tohle bylo opraveno 
v pythonu 2.5 (pokud se nemýlím).

~$ cat test_plus.py
out = ''
for i in range(1000):
out += 'Nebudu komentovat rychlost algoritmů bez měření'
~$ python3 -mcProfile test_plus.py 
 3 function calls in 1.970 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
11.9701.9701.9701.970 test_plus.py:1()
10.0000.0001.9701.970 {built-in method exec}
10.0000.0000.0000.000 {method 'disable' of 
'_lsprof.Profiler' objects}


~$ cat test_append.py
out = []
for i in range(1000):
out.append('Nebudu komentovat rychlost algoritmů bez měření')
outstr = ''.join(out)
~$ python3 -mcProfile test_append.py 
 1004 function calls in 3.331 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
11.8451.8453.3313.331 test_append.py:1()
10.0000.0003.3313.331 {built-in method exec}
 10000.5280.0000.5280.000 {method 'append' of 'list' 
objects}
10.0000.0000.0000.000 {method 'disable' of 
'_lsprof.Profiler' objects}
10.9590.9590.9590.959 {method 'join' of 'str' 
objects}

~$ 

Hezký den,

Matěj

-- 
https://matej.ceplovi.cz/blog/, Jabber: mc...@ceplovi.cz
GPG Finger: 3C76 A027 CA45 AD70 98B5  BC1D 7920 5802 880B C9D8
 
You either die a hero or you live long enough to see yourself become the 
villain.
  -- Harvey Dent in The Dark Knight
___
Python mailing list
python@py.cz
http://www.py.cz/mailman/listinfo/python

Visit: http://www.py.cz


Re: [python] Rekurzivní generátor v Pythonu 3?

2016-08-28 Tema obsahu Petr Messner

> co takhle tohle?
> 
> a b  c de f g h
> 

Oprava:

a b  c de f g h

PM___
Python mailing list
python@py.cz
http://www.py.cz/mailman/listinfo/python

Visit: http://www.py.cz

Re: [python] Rekurzivní generátor v Pythonu 3?

2016-08-28 Tema obsahu Petr Messner
> 
> V mém případě může část dokumentu vypadat třeba takto:
> 
>text text
>
>textB textB  textC textC  textD textD 


Na tohle se vykašli. Jakmile dokument nemá stromovou strukturu, tak je vše 
tisíckrát složitější. Dikybohu toto XML neumí. 

Co je špatného na tom příkladě se sID/eID? Jestli je to v tom, že to neoznačuje 
i část obsahu/verše, co takhle tohle?

a b  c de f g h

Na pochopení toho kódu bych si musel sednout někam v klidu, ale zatím jen 
taková drobnost - nedělej skládání řetězců stylem txt += part, je to strašně 
pomalé (O(n^2) místo O(n)).. Z txt si udělej list a používej append: 
txt.append(part) a na konci "".join(txt).

Petr Messner

27. 8. 2016 v 23:09, Matěj Cepl :

> Dobrý den,
> 
> zkouším napsat v Pythonu 3.4+ nástroj pracující s milestonovanými XML soubory 
> (zdrojové texty překladu Bible).  Podrobně jsem to popsal v blogpostu 
> https://matej.ceplovi.cz/blog/parsing-milestoned-xml-in-python.html, zde 
> jenom velice stručně. Milestones (milníky?) jsou metoda jak obejít 
> neschopnost XML pracovat s několika překrývajícími se hierarchiemi v jednom 
> souboru. Tak třeba právě v biblických textech (TEI se potýká s podobnými 
> problémy) je základní struktura kniha-kapitola-verš, ale přes to jsou další 
> elementy které se překrývají. Několik veršů (nebo jejich částí) jsou sdruženy 
> do logických oddílů (ale některé začínají v půli verše a často přesahují 
> hranice kapitol), nebo třeba zejména anglické biblické překlady mají v oblibě 
> značit výroky Pána Ježíše zvlášť (což pochopitelně často začíná a končí v 
> půli verše).
> 
> Jedna z metod (používaná husta právě v biblických textech, TEI a podobných 
> složitě strukturovaných dokumentech) jsou právě milníky. Takže místo aby byl 
> text značen nějak takto:
> 
> 
> 
> text
> ...
> 
> ...
> 
> 
> použijí se na hranici knihy, kapitoly i verše milníky takto (buď se zvláštním 
> označením konce veršů nebo taky ne):
> 
> 
> 
> text of verse 1.1
>  
> 
> 
> V mém případě může část dokumentu vypadat třeba takto:
> 
>text text
>
>textB textB  textC textC  textD textD 
> 
> A chtěl bych aby moje knihovna naparsovala toto XML a vyprodukovala takovýto 
> seznam:
> 
>[(1, 1, "text text", ['text text']),
> (1, 2, "textB textB textC textC",
>  ['', 'textB textB', '', 'textC textC']),
> (1, 3, "textD textD", ['', 'textD textD', ''])]
> 
> (první dvě čísla jsou číslo kapitoly a verše, poslední položka tuplu je 
> seznam kousků XML v podobě přijatelné pro ElementTree.fromstringlist). Takže 
> představoval bych si generátor, který by byl schopen takovéto API:
> 
>if __name__ == '__main__':
>xml_file = ET.parse('tests/data/Mat-old.xml')
>parser = ET.XMLParser(target=ET.TreeBuilder())
> 
>with open('test.txt', 'w', newline='\r\n') as out_txt, \
>open('test.xml', 'w', newline='\r\n') as out_xml:
>for ch, v, verse_txt, verse_xml in recursive_parse(xml_file):
>print(verse_txt, file=out_txt)
># or directly parser.feed(verse_xml)
># if verse_xml is not a list
>parser.feed(''.join(verse_xml))
> 
>print(ET.tostring(parser.close(), encoding='unicode'),
>  file=out_xml)
> 
> Po různých peripetiích (popsaných v tom zmiňovaném blogpostu) jsem v 
> současném okamžiku u tohoto (zatím bez shromažďování XML kousků):
> 
>def __iter__(self) -> Tuple[CollectedInfo, str]:
>"""
>iterate through the first level elements
>"""
>cur_chapter = 0
>cur_verse = 0
>collected_txt = ''
># collected XML is NOT directly convertable into Element objects,
># it should be treated more like a list of SAX-like events.
>#
># xml.etree.ElementTree.fromstringlist(sequence, parser=None)
># Parses an XML document from a sequence of string fragments.
># sequence is a list or other sequence containing XML data fragments.
># parser is an optional parser instance. If not given, the standard
># XMLParser parser is used. Returns an Element instance.
>#
># sequence = ["", "text"]
># element = ET.fromstringlist(sequence)
># self.assertEqual(ET.tostring(element),
># b'text')
> 
>for child in self.root.iter():
>if child.tag in ['titulek']:
>collected_txt += '\n{}\n'.format(child.text)
>collected_txt += child.tail or ''
>if child.tag in ['kap', 'vers']:
>if collected_txt and collected_txt.strip():
>yield CollectedInfo(cur_chapter, cur_verse,
>re.sub(r'[\s\n]+', ' ', collected_txt,
>   flags=re.DOTALL).strip()), \
>child.tail or ''
> 
>if child.tag == 'kap':
>