Nie jesteś zalogowany.
Jeśli nie posiadasz konta, zarejestruj je już teraz! Pozwoli Ci ono w pełni korzystać z naszego serwisu. Spamerom dziękujemy!

Ogłoszenie

Prosimy o pomoc dla małej Julki — przekaż 1% podatku na Fundacji Dzieciom zdazyć z Pomocą.
Więcej informacji na dug.net.pl/pomagamy/.

#1  2007-11-01 16:33:47

  harry666t - Członek DUG

harry666t
Członek DUG
Zarejestrowany: 2007-01-28

IPython

Wszyscy obecni zgadzają się ze stwierdzeniem, że praca w trybie tekstowym nierzadko jest szybsza, wygodniejsza, itd itp, prawda? :) otóż pomyślałem sobie, bash i generalnie shell uniksowy jest OK, ale ma swoje wady.

A jak coś wokół mnie nie działa, to to naprawiam.

Tak w sumie to pozazdrościłem dotnetowcom ich Monada, i możliwości pracy na obiektach (zamiast strumieni tekstu).

Początkowo miałem bardzo ambitny plan napisania własnego shella w Pythonie. Nawet działał. Porwałem sporo kodu z kilku innych projektów, i miał: customizowalny prompt, anonimowe pipe'y, kontrolę zadań (bg, fg, ^Z, jobs, kill, itd), bloki warunkowe i pętle, i parę tam innych bzdur. Gdy zacząłem go przerabiać do pracy na obiektach, zrozumiałem że zwykły shell ze zwykłymi programami nie podoła - każdy program powinien być funkcją w pythonie, a najlepiej obiektem (niech żyje Java...)... Dobra, do rzeczy. Oczywiście projekt upadł, jak wszystkie poprzednie.

Wróciłem na parę tygodni do basha. Pewnego dnia, podczas pracy nad gierką w pygame zacząłem rozglądać się nad narzędziami do debugowania i profilowania kodu w pythonie. No i trafiłem na luźno związanego z tematem IPythona.

Zacytuję z opisu paczki:

IPython can be used as a replacement for the standard Python shell, or it can be used as a complete working environment for scientific computing (like Matlab or Mathematica) when paired with the standard Python scientific and numerical tools. It supports dynamic object introspections, numbered input/output prompts, a macro system, session logging, session restoring, complete system shell access, verbose and colored traceback reports, auto-parentheses, auto-quoting, and is embeddable in other Python programs.[/quote]

W opisie sporo o matematyczno-naukowych zastosowaniach IPy, ale olać to. Prawdziwą moc widać gdy spróbujemy zacząć używać go jako zastępcy dla basha. Oczywiście nie był planowany ani pisany z myślą o tym zastosowaniu, ale czas to naprawić. A że Python jest bardzo pięknym językiem, owa naprawa to żadna robota :)

Pierwszy krok to apt-get install ipython. Po chwili odpalam IPy, i zaczynam się bawić. Już na wstępie IPy sugeruje parę ciekawych opcji: %magic oraz system introspekcji obiektów. Zacznę od tego drugiego.

Powiedzmy że jest jakaś ciekawa fajna komenda, no powiedzmy że ciekawie brzmi. W bashu czy zsh dajemy man <cmd> i wczytujemy się w długi opis. W IPy, powiedzmy:

Kod:

In [1]: ls?
Type:           System alias
Base Class:     <type 'tuple'>
String Form:    (0, 'ls -F')
Namespace:      Alias
Length:         2
Docstring:
    Alias to the system command:
      ls -F

Imho bardzo wygodne. W podobny sposób można sprawdzić zawartość dowolnej zmiennej czy uzyskać szczegółowe info na temat dowolnego obiektu.

Warto zauważyć że jeżeli wyjście nie zmieści się w całości na ekranie, IPy sam się domyśli, że dobrze jest je puścić przez less.

Działa też coś takiego jak dopełnianie nazw tabem. W zwykłym interpreterze Pythona aby uzyskać podobny efekt należy ustawić jakąś zmienną środowiskową która wskaże plik konfiguracyjny i w owym pliku zaimportować kilka modułów, pamiętając o try:...except oczywiście. Nie każdemu się chce :P W IPy dopełnianie działa zarówno dla nazw zmiennych, funkcji, klas, metod, aliasów, magii, jak i ścieżek do plików.

A właśnie, magia. Polecenia takie jak cd, bg czy edit korzystają z "magicznych" funkcji napisanych bezpośrednio w Pythonie. Oczywiście można je dodawać samemu, ale by stało się to opcją należy lekko przetjuningować konfigurację IPy.

Otwieramy plik '~/.ipython/ipythonrc'. Można sobie pozmieniać różne opcyjki, ale zejdźmy do polecenia execfile (tutaj mała uwaga, składnia owego pliku konfiguracyjnego ma niewiele wspólnego ze składnią samego IPy - dlatego zaraz dodamy prawdziwy plik rc). W mojej domyślnej instalacji znajduje się w okolicach linii 570. Dodajemy gdzieś tutaj:

Kod:

execfile ~/.ipythonrc.py

Oczywiście nazwę można sobie wybrać :D

Odwiedzamy ów plik i dodajemy następujący kod, (C) by ja, licencja dowolna OSS wedle uznania, gwarancji brak, i tak dalej. No dobra, przerobiłem go z example-magic.py :)

Kod:

def newmagic_hello(self,parameter_s=''):
    """Tutaj króciutki opis funkcji."""
    print "Hello, world!"

from IPython.iplib import InteractiveShell
for numagic in dir():
    if numagic[0:9] == "newmagic_"
        exec "InteractiveShell.magic_"+numagic[9:]+" = newmagic_"+numagic[9:]
        exec "del " + numagic

Teraz wystarczy dodawać kolejne funkcje według konwencji:

Kod:

def newmagic_nazwafunkcji(self, parameter_s=''):
    ...

Uwaga na listę parametrów, IPy oczekuje dokładnie takiej i żadnej innej (aby uzyskać efekt podobny do argv[1:argc] wystarczy wziąć wynik parameter_s.split(" ")).

No dobra, i co w tym takiego zajefajnego? Otóż pomyślałem o wykorzystaniu modułu pickle aby transportować obiekty pomiędzy owymi magicznymi funkcjami. Ale możliwe że ktoś wpadnie na lepszy pomysł. Na początek jednak wziąłem już na stół polecenia ps, kill, i tym podobne. Możliwe że kiedyś "[]: ps | where user wredna_siostra | kill" stanie się rzeczywistością :D

Niedawno byłem wielkim fanem "zwykłego" interpretera Pythona. Jednakże po pracy z CLispem brakowało mi automatycznego odpalania debuggera przy wyjątkach. Otóż można skonfigurować IPy (tylko już nie pamiętam gdzie :P) by przy niepochwyconym wyjątku uruchamiał pdb. I od CLispa różni się też tym, że można z niego wyjść szybkim ^D. To taki sajdnołt.

A właśnie - apropos lispa. Znienawidziłem nawiasy. Toteż bardzo ucieszyłem się z kolejnej magii: [b]nawiasy są w IPy mniej więcej zbędne[/b]. Mniej więcej tak (fragmencik sesji):

Kod:

In [4]: str 4+3j
------> str(4+3j)
Out[4]: '(4+3j)'

In [5]: def foo(bar):
   ...:     print bar
   ...: 

In [6]: foo 'masakra!'
------> foo('masakra!')
masakra!

O ile zestaw parametrów dla funkcji jest jednoznaczny (na przykład nie próbujemy wdusić samych dwóch czy trzech krotek, co IPy może pomylić z wywołaniem rezultatu funkcji jako kolejnej funkcji), nawiasy okazują się zbędne. Działa też na obiektach:

Kod:

In [7]: class bar:
   ...:     def __init__(self):
   ...:         pass
   ...: 

In [8]: bee = bar()

In [9]: foo bee
------> foo(bee)
<__main__.bar instance at 0xb77e7f2c>

In [10]: foo bar
-------> foo(bar)
__main__.bar

Z przydatnych bajerów jest też autoquote. Czasem tak mi się absolutnie nie chce wpisywać cudzysłowów że aż się zastanawiam czy autorzy IPy nie czytali moich myśli gdy zastanawiali się jak jeszcze można ulepszyć ten program:

Kod:

In [11]: ;foo bar
-------> foo("bar")
bar

Czyli wystarczy poprzedzić nazwę funkcji średnikiem. Gwoli ścisłości, działa też z przecinkiem, tylko nie kojarzę różnicy...

Podczas tworzenia mojej gierki zainteresowałem się też wątkami w Pythonie. IPy ma jednakże coś o wiele piękniejszego od modułów thread i threading; wątki można startować podobnie jak z użyciem & w bashu, podając po prostu nazwę funkcji do wywołania jako argument dla polecenia bg:

Kod:

In [12]: bg foo('meow')
Starting job # 0 in a separate thread.
In [13]: meow
In [14]: 

Jak to już bywa z m-t I/O jest kiepsko zsynchronizowane :P

Nic mi nie wiadomo na temat jakiejkolwiek obsługi zwykłych anonimowych pipe'ów, jednak skoro pracujemy na obiektach, nie robi to aż takiej różnicy. Pracuję właśnie nad dostosowaniem IPy do normalnej pracy, tak aby stał się w praktyce zamiennikiem dla uniksowego shella, i na liście TODO umieściłem implementację łatwych w użyciu ekwiwalentów wszystkich standardowych poleceń uniksa. Jak będzie gotowe to gdzieś porzucę.

Aha, no i na koniec (ktoś doczytał aż tutaj!?) gdyby ktoś zatęsknił za bashem, można wywoływać normalne polecenia powłoki, poprzedzając je wpierw wykrzyknikiem, ot tak:

Kod:

In [14]: !ls /usr/share/doc | grep python
ipython
python
python2.4
python2.4-minimal
python-apt
python-beagle
python-cairo
(ciach...)

Dla mnie IPython jest przedłużeniem zwykłego shella Pythona. Jest do innych shelli niczym fvwm do innych menedżerów okien. Jest do innych języków programowania jak... No, tutaj nie mam porównania... Nieważne. Jest po prostu genialny.

Aha, jest też automatyczna indentacja, numerowanie I/O (można się dostać do wyników poprzednich poleceń), aliasy dla komend basha, pełne wsparcie readline (wraz z reverse I-search), zapisywanie sesji (aczkolwiek tego jeszcze nie próbowałem), bardzo ślicznie pokolorowane ślady przy nieobsłużonych wyjątkach, o debugerze wspominałem, magiczne ? potrafi też ponoć jakoś wyświetlać pełny kod klas i funkcji, historia katalogów odwiedzanych przez cd, i pewnie jeszcze pełno innych rzeczy, które odkryję jak tylko zechce mi się spojrzeć w kod :D

Wszystkim kochającym środowisko tekstowe, i/lub ewentualnie Pythona, polecam pobawić się trochę z tą paczką, bo to jest po prostu genialne. O tym że IPy jest moją powłoką logowania już wspominałem? :)


[ /\/\/\ o_0 ----->>>       Ascii Art Userbar User ]

"steal and steal and steal some more and give it to all your friends and keep on stealin'"
- Reznor

Offline

 

#2  2007-11-01 17:02:09

  czadman - Bicycle repairman

czadman
Bicycle repairman
Skąd: Wrocław
Zarejestrowany: 2005-07-08

Re: IPython

Ciekawy tekst. :)


[url=http://www.debian.org/][img]http://www.debian.org/logos/openlogo-nd-50.png[/img][/url]

Offline

 

#3  2007-11-01 18:16:52

  LongeR - Członek DUG

LongeR
Członek DUG
Skąd: DT
Zarejestrowany: 2007-09-03
Serwis

Re: IPython

Przykleić!!


[b]LongeR rządzi, LongeR radzi, LongeR nigdy cię nie zdradzi!![/b]
-->Nic na siłę, lekko młotkiem:D<----> Czy myślenie sprawia Ci ból?<--
Nieważne od czego się zaczyna - kończy się zawsze na Debianie : )
Linux register users: #456947

Offline

 

#4  2017-09-21 20:48:59

  PawSta1990 - Nowy użytkownik

PawSta1990
Nowy użytkownik
Skąd: Katowice
Zarejestrowany: 2017-09-21
Spam…

Re: IPython

Również uważam, że jest to bardzo przydatny i wartościowy artykuł. Dzięki :)


[url]http://seansobox.pl[/url]

Offline

 

#5  2017-09-21 22:21:10

  lis6502 - Łowca lamerów

lis6502
Łowca lamerów
Skąd: Stalinogród
Zarejestrowany: 2008-12-04

Re: IPython

[img]http://wstaw.org/m/2017/09/21/download.jpg[/img]

Offline

 

#6  2017-09-21 23:14:30

  urbinek - Użytkownik

urbinek
Użytkownik
Skąd: Sosnowiec
Zarejestrowany: 2009-10-01
Serwis

Re: IPython

Te boty są coraz lepsze :D


A w wolnym czasie, robię noże :)
[img]http://nginx.urbinek.eu/_photos/signature.png[/img]

Offline

 

#7  2017-09-22 16:58:40

  mati75 - Psuj

mati75
Psuj
Skąd: default city
Zarejestrowany: 2010-03-14
Serwis

Re: IPython

To nie boty to linkbuilderzy - studenci za 60 gr brutto za link. Mam takich paru "bardzo wartościowych" w firmie.


[img]https://l0calh0st.pl/obrazki/userbar.png[/img]

Offline

 

Stopka forum

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson
Nas ludzie lubią po prostu, a nie klikając w przyciski ;-)

[ Generated in 0.008 seconds, 11 queries executed ]

Informacje debugowania

Time (s) Query
0.00011 SET CHARSET latin2
0.00004 SET NAMES latin2
0.00127 SELECT u.*, g.*, o.logged FROM punbb_users AS u INNER JOIN punbb_groups AS g ON u.group_id=g.g_id LEFT JOIN punbb_online AS o ON o.ident='3.145.184.33' WHERE u.id=1
0.00065 REPLACE INTO punbb_online (user_id, ident, logged) VALUES(1, '3.145.184.33', 1733247855)
0.00040 SELECT * FROM punbb_online WHERE logged<1733247555
0.00050 SELECT topic_id FROM punbb_posts WHERE id=74205
0.00094 SELECT id FROM punbb_posts WHERE topic_id=9573 ORDER BY posted
0.00061 SELECT t.subject, t.closed, t.num_replies, t.sticky, f.id AS forum_id, f.forum_name, f.moderators, fp.post_replies, 0 FROM punbb_topics AS t INNER JOIN punbb_forums AS f ON f.id=t.forum_id LEFT JOIN punbb_forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id=3) WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.id=9573 AND t.moved_to IS NULL
0.00005 SELECT search_for, replace_with FROM punbb_censoring
0.00110 SELECT u.email, u.title, u.url, u.location, u.use_avatar, u.signature, u.email_setting, u.num_posts, u.registered, u.admin_note, p.id, p.poster AS username, p.poster_id, p.poster_ip, p.poster_email, p.message, p.hide_smilies, p.posted, p.edited, p.edited_by, g.g_id, g.g_user_title, o.user_id AS is_online FROM punbb_posts AS p INNER JOIN punbb_users AS u ON u.id=p.poster_id INNER JOIN punbb_groups AS g ON g.g_id=u.group_id LEFT JOIN punbb_online AS o ON (o.user_id=u.id AND o.user_id!=1 AND o.idle=0) WHERE p.topic_id=9573 ORDER BY p.id LIMIT 0,25
0.00078 UPDATE punbb_topics SET num_views=num_views+1 WHERE id=9573
Total query time: 0.00645 s