Anda di halaman 1dari 142

1

2
PRAKATA PRAKATA PRAKATA PRAKATA

Penyusunan buku ini banyak didukung oleh banyak pihak baik


secara langsung maupun tidak langsung. Oleh karena itu, penulis
inginmengucapkanthanxsomuchto:

Allahyangmemilikikekuasaantiadabatas
Rasulullahatassegalasyafaatnya
Buya&Umaatassegalakasihsayangnya
Mala&Novrianayangselalumemberisemangat
STMlKAMlKOMYogyakartadengankenyamanan
fasilitasnya
TitixKostCommunityyangselalumenghibur
BuEmayangtetapsabarmembimbing
Temen-temenKelompokStudiGNU/LinuxAmikom
sebagaiinspirator
Dansemuapihakyangtidakbisadisebutkansatupersatu

Yogyakarta,November2006


3
DAFTARlSl DAFTARlSl DAFTARlSl DAFTARlSl

MENGAPAPYTHON++? .......................... 1
SETUP ....................................... 1
PEMANASAN(Newbieisrequired) .................. 2
MenjalankanPython .......................... 2
lndentasi ................................... 3
TipeData .................................... 3
1.Bilangan ............................... 4
2.String ................................. 5
LlST .......................................... 7
TUPLE ......................................... 9
DlCTlONARY .................................... 11
STATEMENDASAR .............................. 13
Seleksi ..................................... 13
Perulangan .................................. 15
SubrutinatauFungsi ........................... 17
AturanLGB ................................. 20
Eksepsi .................................... 22
Class ....................................... 25
Module ..................................... 34
lnputdanOutput .............................. 40
OperasiFile .................................. 41
OperasiWaktu ............................... 43
XMLRPC ...................................... 45
PYGRESQL .................................... 50
lnstalasidanKonfigurasiPostgreSQL .............. 50
MenjalankanPostgreSQL ....................... 51
MembuatDatabase ........................... 53
QueryDatabase .............................. 55
lnstalasidanKonfigurasiPygreSQL ............... 56
ModuleDatabasePostgreSQL ................... 58
KoneksiDatabase ............................. 58
Query ...................................... 59
Method-MethodKoneksi ........................ 62

4
GUlPYTHON .................................... 69
PYGTK ......................................... 70
GtkWindow .................................. 77
GtkFrame ................................... 80
GtkEntry ..................................... 82
GtkComboBox ............................... 84
GtkRadioButton ............................... 87
GtkTreeView ................................. 89
GtkButtondanGtkButtonBox ..................... 91
GtkMessageDialog ............................. 96
MenudanToolbar ............................. 99
BONUS ........................................ 105



5
MENGAPAPYTHON++? MENGAPAPYTHON++? MENGAPAPYTHON++? MENGAPAPYTHON++?
Python++ bukanlah sebuah bahasa pemograman baru dan
juga tidak ada hubungannya dengan C++. Huruf "++ di belakang
kata Python hanya sekedar meniru gaya pemberian sebutan
sesuatuyangdianggapbedadanataumemilikikelebihan.Namun
tidak berarti sesuatu yang berbau porno dimana sangat erat
denganhuruf"++.
Beda, itu yang membuat bahasa Python cukup aneh baik
untuk didengar maupun digunakan. Yang terbayang di benak kita
pastisuatuhewanreptilyangbuasdanberbisa,sisiinitidakbegitu
istimewa untuk dibahas. Sisi utama yang membedakan Python
dengan bahasa lain adalah dalam hal aturan penulisan kode
program. Bagi para programmer di luar python siap-siap
dibingungkan dengan aturan indentasi, tipe data, tuple, dan
dictionary. Python memiliki kelebihan tersendiri dibandingkan
dengan bahasa lain terutama dalam hal penanganan modul, ini
yangmembuatbeberapaprogrammerbenar-benarfallinlovepada
python. Selain itu python merupakan salah satu produk yang
opensource,free,danmultiplatform.
Kembalipadahuruf"++diatas,bukuiniakanmembuktikan
dan membahas penggunaan python pada beberapa aplikasi
secara "++. Bagaimana cara "++ yang dimaksud, read the f--n
manual:D!!!

SETUP SETUP SETUP SETUP


Aplikasi python umumnya telah disertakan dalam paket
distribusi GNU/Linux. Untuk melakukan instalasi bisa melalui
source ataupun paket yang telah disediakan. lnstalasi melalui
paket distribusi slackware bisa melakukan perintah 'installpkg
python-xxx.tgz'. Untuk jenis rpm perintahnya 'rpm -ivh python-
xxx.rpm'. lnformasi lengkap mengenai instalasi aplikasi di

6
GNU/Linuxsilahkandipelajarisendiri:P.

PEMANASAN PEMANASAN PEMANASAN PEMANASAN(Newbieisrequired) (Newbieisrequired) (Newbieisrequired) (Newbieisrequired)


Sebelum mengenal python secara mendalam, perlu kiranya
belajar basicnya dahulu. Namun sah-sah saja bagi mereka yang
ingin melewatkan bagian ini. Bagian ini akan dijelaskan sedikit
konsepmengenaifungsi-fungsi,modul,danpenulisankodedalam
pythonbesertapenerapannyadalamcontohaplikasi.

MenjalankanPython MenjalankanPython MenjalankanPython MenjalankanPython


Dalammenuliskodeprogrambisadilakukandengan2cara
yakni melalui modus interaktif semacam prompt shell Linux atau
menulis kode dalam sebuah skrip. Modus interaktif sangat cocol
untuk melakukan pemograman ataupun pengujian sederhana
dimana penggunaan aplikasinya hanya saat itu. Sedangkan untuk
membuataplikasiyangkomplekdannantinyaakandigunakanlagi
pilih modus skrip. Untuk menggunakan modus interaktif cukup
mengetikkan perintah 'python' pada shell linux sehingga akan
muncultampilansebagaiberikut:

Python 2.4.1 (#1, Apr 10 2005, 22:30:36)


[GCC 3.3.5] on linux2
Type "help", "copyright", "credits" or "license"
for more information.
>>>

Tanda '>>>' manandakan interpreter python siap menerima


perintah atau kode program. Ada juga tanda ... yang berarti baris
berikutnyadalamsuatublokprompt'>>>'.Untukmodusskripbisa
menggunakan text editor seperti kwrite, kate, vi, dll. Berikut
contohnyadengannamafiletes:


7
#!/usr/bin/python
import time
print time.ctime()

Selanjutnya untuk menjalankan skrip di atas bisa dengan 2


cara yakni dengan mengetikkan perintah 'python tes' atau dengan
menambahkan nilai permission x untuk executable dengan
perintah 'chmod +x tes', lalu jalankan programnya dengan
mengetikkan'./tes'.

lndentasi lndentasi lndentasi lndentasi


Hal yang perlu diperhatikan dalam gaya penulisan kode
padapythonadalahmasalahindentasi.Penggunaanindentasibisa
berupa spasi atau tabulasi, agar tidak rancu dan menghidari
kesalahan pilih salah satu dalam penulisan kode program. Berikut
contohpenggunaannya:

>>> a=1
>>> if a==1:
... print 'nilai a=1'
... print 'benar'

>>> if a==1:
... print 'nilai a=1'
... print 'benar'

>>> if a==1:
... print 'nilai a=1'
... print 'salah'

TipeData TipeData TipeData TipeData


Kemampuan python dalam mengelola tipe data patut
diacungkan jempol. Untuk mendeklarasikan suatu variabel
dilakukan secara langsung tanpa menyebutkan tipe datanya, ini
yang membedakan dengan python bahasa lain. Python akan
menentukan tipe datanya secara otomatis. Python juga
mendukung konversi dan perhitungan antar tipe data dengan
ketelitian yang tinggi. Untuk mempermudah kita bagi ke dalam 2
Benar
Benar
Salah

8
jenisyaknibilangan(semuatipeyangberhubungandenganangka
murni)danstring.

1. 1. 1. 1.Bilangan Bilangan Bilangan Bilangan


Untuk tipe data dalam rumpun bilangan termasuk di
dalamnya adalah integer, long, float, oktal, hexadesimal, dan
bilangankompleks.Hal-halyangharusdiperhatikan:
untuk bilangan oktal dan hexa masing-masing diawali
dengan0dan0x
untuk bilangan yang panjang diakhiri dengan karakter l
atauL
untukbilanganfloat,gunakaneatauEpadaeksponensial
untuk bilangan kompleks dibagi ke menjadi bagian real
danimajiner,dandiakhiridenganjatauJ

Operator-operator untuk tipe dalam rumpun bilangan dapat dilihat


padatabelberikut:

Operator Operator Operator Operator Keterangan Keterangan Keterangan Keterangan


+
-
*
/
%
**

>>
<<
|
&
^
>,>=
<,<=
==
!=atau<>
penjumlahan
pengurangan,negasi
perkalian
pembagian
sisapembagian
pemangkatan
bitwisekomplemen
bitwiseshiftright
bitwiseshiftleft
bitwiseor
bitwiseand
bitwisexor
perbandinganlebihbesardansamadengan
perbandinganlebihkecildansamadengan
perbandingansamadengan
perbandingantidaksamadengan


9
Beberapafungsiyangberlaku:
Fungsi Fungsi Fungsi Fungsi Keterangan Keterangan Keterangan Keterangan
abs(a)
pow(a,b)
int(c)
menghasilkannilaimutlakdaria
menghitungpemangkatanaolehb
konversidatacketipedatainteger

Berikutcontohpenggunaannya:

>>> a=2
>>> b='6'
>>> a+int(b)
8
>>> c=int(b)
>>> a**c
64
>>> pow(a,c)
64

2 22 2.String .String .String .String


Dalam menangani penggunaan string python dapat
diandalkan,denganaturansebagaiberikut:
diapittandakutiptunggal(')atauganda(")
biladidalamsuatustringterdapatkarakterkutiptunggal(')
penulisannyadiapitkutipganda(")
biladidalamsuatustringterdapatkarakterkutiptunggal(")
penulisannyadiapitkutipganda(')

Operator-operator untuk tipe data string dapat dilihat pada tabel


berikut:

Operator Operator Operator Operator Keterangan Keterangan Keterangan Keterangan


+
*
>
<
==
penjumlahan
pengulangan
perbandinganlebihbesar(jumlahkarakter)
perbandinganlebihkecil
samadengan

10
Operator Operator Operator Operator Keterangan Keterangan Keterangan Keterangan
!=atau<>
in
tidaksamadengan
anggotahimpunan

Beberapafungsiyangberlaku:
Fungsi Fungsi Fungsi Fungsi Keterangan Keterangan Keterangan Keterangan
len(a)
str(b)
menghitungpanjangsuatustring
konversidatabketipedatastring

Bagi programmer gaya C pasti mengenal fungsi substring


atau bagi programmer VB ada fungsi left, mid, dan right yang
berfungsi dalam mengakses indeks ataupun melakukan irisan
suatu string. Python dalam hal ini juga dapat diandalkan, tanpa
menggunakan fungsi khusus. Untuk mengakses indeks dilakukan
layaknyamengaksesarray.Sedangkanuntukirisanmenggunakan
notasi string[awal:akhir]. Agar tidak bingung dengan teori-teori di
atasberikutcontohnya:

>>> a=2
>>> b='6'
>>> str(a)+b
'26'
>>> b*4
'6666'
>>> c=mother's home
>>> len(c)
13
>>> 'm' in c
True
>>> d='python termasuk interpreter'
>>> c[0]
'm'
>>> d[14]
'k'
>>> d[0:6]
'python'
>>> d[16:]
'interpreter'
>>> d[-13:]
'interpreter'

11
Beberapahalyangperludiketahuidaricontohdiatas:
string bersifat immutable yakni nilai suatu indeks string
tidakdapatdiubah
untuk irisan dengan notasi positif pembacaan indeksnya
dimulaidari(0)darikirikekanan
untuk irisan dengan notasi negatif pembacaan indeksnya
dimulaidari(-1)darikanankekiri

Dari penjelasan di atas, untuk melakukan perubahan nilai


padaindekstertentubisamemanfaatkanirisansepertiberikut:

>>> e='M'+c[1:]
>>> e
Mother's home


LlST LlST LlST LlST
List dapat disamakan dengan array pada bahasa C. List
bergunasekalibilakitamemilikibanyakdatadenganberbagaitipe,
akandirasakanbilamembuatprogramyangkomplek.Hal-halyang
perludiperhatikan:
list bersifat mutable sehingga nilai suatu indeksnya bisa
diubah
aturanlainnyasamasepertiperlakuantipedatastring

Operator-operatoruntuklistdapatdilihatpadatabelberikut:

Operator Operator Operator Operator Keterangan Keterangan Keterangan Keterangan


+
*
>
<
==
!=atau<>
in
penggabunganlist
pengulangan
perbandinganlebihbesar(jumlahanggota)
perbandinganlebihkecil
samadengan
tidaksamadengan
anggotahimpunan

12
Beberapafungsiyangberlaku:
Fu Fu Fu Fungsi ngsi ngsi ngsi Keterangan Keterangan Keterangan Keterangan
len(a)
del(a[i])
list(b)
menghitungpanjangsuatulist
menghapusdatalistpadaindeksi
menghasilkanlistdengandatabsebagai
anggotahimpunan

Beberapa method yang sangat berguna dalam memanipulasi list


diantaranya:

Method Method Method Method Keterangan Keterangan Keterangan Keterangan


append(b)
sort()
count(b)
extend(list)
index(b)
insert(i,b)
pop(i)

remove(b)
reverse()
menambahkandatabdiakhirlist
mengurutkansebuahlist
menghasilkanjumlahanggotabdalamlist
menambahkandataberupalistpadaakhirsuatulist
mendapatkanindeksdarikemunculanpertamadarib
menyisipkandatabsebelumindeksi
menghapusdatapadaindexi,defaultnyanilaipaling
akhir
menghapusdatabyangmunculpertamakali
membalikanggotadatasuatulist

Untuklebihjelasnyaperhatikancontohberikut:

>>> a='bersiaplah'
>>> b=list(a)
>>> len(b)
10
>>> del(b[9])
>>> del(b[7:9])
>>> b
['b', 'e', 'r', 's', 'i', 'a', 'p']
>>> b.append['l']
>>> c=['a','h']
>>> b.extend(c)
>>> b
['b', 'e', 'r', 's', 'i', 'a', 'p', 'l', 'a', 'h']
>>> b.sort()
>>> b

13
['a', 'a', 'b', 'e', 'h', 'i', 'l', 'p', 'r', 's']
>>> b.reverse()
>>> b
['s', 'r', 'p', 'l', 'i', 'h', 'e', 'b', 'a', 'a']
>>> b.insert(2,20)
>>> b
['s', 'r', 20, 'p', 'l', 'i', 'h', 'e', 'b', 'a', 'a']
>>> b.pop(2)
20
>>> b
['s', 'r', 'p', 'l', 'i', 'h', 'e', 'b', 'a', 'a']
>>> b.count('a')
2
>>> b.index('a')
8
>>> b.remove('a')
>>> b
['s', 'r', 'p', 'l', 'i', 'h', 'e', 'b', 'a']
>>> d=[4,['5','6']]
>>> b+d
['s', 'r', 'p', 'l', 'i', 'h', 'e', 'b', 'a', 4, ['5',
'6']]
>>> d*2
[4, ['5', '6'], 4, ['5', '6']]
>>> 4 in d
True
>>> b[2:5]
['p', 'l', 'i']
>>> b[6:]=[]
>>> b
['s', 'r', 'p', 'l', 'i', 'h']

TUPLE TUPLE TUPLE TUPLE


Tuple kegunaannya hampir sama dengan list yakni dalam
hal pengumpulan berbagai data. Namun di satu sisi terdapat
perbedaanyangmenonjolantaratupledenganlistyaknidalamhal
penulisan dan sifatnya. Pada list dibatasi tanda kurung siku,
sedangkanpadatupledibatasitandakurungbiasa.Danjugatuple
merupakan object yang immutable. Hal lain yang perlu
diperhatikan untuk tuple dengan satu elemen atau anggota,

14
penulisannya ditambah koma (,) setelah elemen pertama dan
sebelumtandakurungtutup.

Operator-operatoruntuktupledapatdilihatpadatabelberikut:
Operator Operator Operator Operator Keterangan Keterangan Keterangan Keterangan
+
*
>
<
==
!=atau<>
ln
penggabungantuple
pengulangan
perbandinganlebihbesar(jumlahanggota)
perbandinganlebihkecil
samadengan
tidaksamadengan
anggotahimpunan

Beberapafungsiyangberlaku:
Fungsi Fungsi Fungsi Fungsi Keterangan Keterangan Keterangan Keterangan
len(a)
tuple(b)
menghasilkanpanjangsuatutuple
menghasilkansuatutupledengandatab
sebagaielemennya

Contoh:

>>> a=1,
>>> b=2,3,4
>>> a+b
(1,2,3,4)
>>> a*3
(1,1,1)
>>> 3 in b
True
>>> b[2]
4
>>> b[1:3]
(3,4)



15
DlCTlONARY DlCTlONARY DlCTlONARY DlCTlONARY
Dictionarymerupakantipeberupakumpulandatasepertilist
dan tuple namun disajikan dalam bentuk yang tidak berurutan.
Mungkinbagibahasalainpenggunaandictionarysangatanehdan
tidak ada, inilah istimewanya python. Setiap Elemen data dalam
dictionary dibagi menjadi key dan value. Bagi para programmer
yang terbiasa dengan penggunaan seleksi case, akan
kebingungan saat mengenal python karena tidak tersedia. Namun
jangan kecewa dahulu, karena dengan adanya dictionary
permasalahan tersebut dapat dipecahkan. Untuk penjelasan
mengenai seleksi dibahas pada bagian lain. Beberapa hal yang
perludiperhatikan:
untukmengaksesnilaidatamenggunakankeyataukunci,
jadibukannyaindekssepertipadalistdantuple
dictionarymerupakanobjekyangmutable
fungsi penggabungan dan irisan pada dictionary tidak
berlaku
dictionarytidakmemperhatikanurutan

Operator-operatoruntukdictionarydapatdilihatpadatabelberikut:
Operator Operator Operator Operator Keterangan Keterangan Keterangan Keterangan
>
<
==
!=atau<>
in
perbandinganlebihbesar
perbandinganlebihkecil
samadengan
tidaksamadengan
anggotahimpunan

Beberapafungsiyangberlaku:
Fungsi Fungsi Fungsi Fungsi Keterangan Keterangan Keterangan Keterangan
len(a)
del(a[b])
menghasilkanpanjangsuatudictionary
menghapuselemendatadictionaryadengankuncib


16
Sebagaiobjekyangmutable,dictionarymemilikibeberapamethod
sebagaiberikut:

Method Method Method Method Keterangan Keterangan Keterangan Keterangan


clear()
copy()
items()

get(k)
keys()
has_key(k)
popitem()
update(D)
values()
menghapussemuaisidictionary
mengembalikankopisuatulist
menampilkan isi dictionary dalam bentuk tuple
secaraberpasangan
mengembalikannilaidatadarikuncik
menampilkansemuakuncidalamsuatudictionary
mengecekkuncikpadasuatudictionary
menghapusdataawalsuatudictionary
updateisidictionarydenganisidictionaryD
menampilkansemuanilaidalamdictionary

Berikutcontoh-contohnya:

>>> a={1:'nama',2:'umur',3:'status'}
>>> b={1:{'nama':'rido'},2:21,3:'single','group':
['kpli','ksga']}
>>> len(a)
3
>>> b
{1: {'nama': 'rido'}, 2: 21, 3: 'single', 'group':
['kpli', 'ksga']}
>>> del(b['group'])
>>> b
{1: {'nama': 'rido'}, 2: 21, 3: 'single'}
>>> b.keys()
[1, 2, 3]
>>> b.values()
[{'nama': 'rido'}, 21, 'single']
>>> b.has_key(2)
True
>>> b[3]
'single'
>>> b[1]['nama']
'rido'
>>> a.update(b)
>>> a==b
True


17
STATEMENDASAR STATEMENDASAR STATEMENDASAR STATEMENDASAR
Pada bagian ini akan dibahas sekilas tentang statemen-
statemen pada python seperti seleksi, perulangan, dan subrutin
yangnantinyaakanbanyakdigunakanpadapembuatanaplikasidi
bagianlain.

Selek Selek Selek Seleksi si si si


Statemeninihapirselaludigunakandalammelakukansuatu
pemograman. Seleksi dilakukan bila dihadapkan pada kondisi
dimana kita harus memilih. Ada beberapa cara melakukan seleksi
dipythonyaitudiantaranya:

Metode Metode Metode Metode BentukUmum BentukUmum BentukUmum BentukUmum Keterangan Keterangan Keterangan Keterangan
lf

if...else

if...elif...else

ifbersarang
ifkondisi:
statemen

ifkondisi:
statemen
else:
statemen

ifkondisi1:
statemen
s/d
elifkondisi-n:
statemen
else:
statemen

ifkondisi1:
statemen
ifkondisi2:
statemen
seleksi dimana pilihan kondisi
hanyaadasatu

seleksidengan2pilihankondisi

seleksi dengan banyak pilihan


kondisi

seleksididalamseleksi

18
Padabahasalainbiasanyaterdapatcaraseleksiselainyang
disebutkan di atas, contohnya saja pada bahasa C terdapat
statemen switch atau case yang digunakan di pascal. Statemen
yang satu ini tidak dimiliki oleh python. Sebagai gantinya python
menyediakan object dictionary yang dapat diandalkan dalam
melakukan seleksi seperti switch atau case. Untuk lebih jelasnya
perhatikancontoh-contohberikut:

>>> a='aku'
>>> if a=='aku':
... print 'a berarti %s'%a
...
a berarti aku
>>> if a=='antik':
... print 'a berarti %s'%a
... else:
... print 'a berarti %s'%a
...
a berarti aku
>>> a='antik'
>>> if a=='aku':
... print 'a berarti %s'%a
... elif a=='antik':
... print 'a berarti %s'%a
... else:
... print 'a berarti %s'%a
...
a berarti antik
>>> b='borju'
>>> if a=='antik':
... a='aku'
... if b=='borju':
... print '%s anak %s'%(a,b)
... else:
... print '%s bukan anak %s'%(a,b)
...
aku anak borju
>>> seleksi={1:'januari',2:'februari',3:'maret',4:
'april',5:'mei'}
>>> bulan=3
>>> seleksi[bulan]
'maret'


19
Perulangan Perulangan Perulangan Perulangan
Dalam melakukan statemen perulangan, penulis sangat
kagum dengan kinerja python. Ada hal yang menarik dari cara
python melakukan perulangan yaitu adanya fungsi in dan range
pada perulangan dengan for. Untuk lebih jelasnya perhatikan
contohberikut:

>>> a=1
>>> while a<5:
... print a,
... a+=1
...
1 2 3 4
>>> a=0
>>> while a<10:
... a+=1
... if a%2:
... print '%d bilangan ganjil'%a
... else:
... continue
...
1 bilangan ganjil
3 bilangan ganjil
5 bilangan ganjil
7 bilangan ganjil
9 bilangan ganjil
>>> a=1
>>> while a<10:
... print a,
... a+=1
... if a>6:
... break
...
1 2 3 4 5 6
>>> while 1:
... print 'perulangan tiada batas, tekan ^C
Untuk berhenti'
...
perulangan tiada batas, tekan ^C untuk berhenti
perulangan tiada batas, tekan ^C untuk berhenti
......
>>> a=1
>>> while a<5:
... print a,
... a+=1
... else:

20
... print 'selesai'
...
1 2 3 4 selesai
>>> for a in range(1,5):
... print a,
...
1 2 3 4
>>> for a in range(1,10,2):
... print '%d bilangan ganjil'%a
...
1 bilangan ganjil
3 bilangan ganjil
5 bilangan ganjil
7 bilangan ganjil
9 bilangan ganjil
>>> bulan={1:'januari',2:'februari',3:'maret',4:
'april',5:'mei'}
>>> for a in bulan.values():
... print a
...
januari
februari
maret
april
mei
>>> s='ini sebuah string'
>>> for a in s:
... print a,
...
i n i s e b u a h s t r i n g
>>> t=1,'aku',5.6,6666666L,['a','b','c']
>>> for a in t:
... print a,
...
1 aku 5.6 6666666 ['a', 'b', 'c']
>>> for a in t[4]:
... print a,
...
a b c

Coba perhatikan bagian perulangan for, python


melakukannya dengan sangat teliti dan efisien. Kita dapat
memecahelemendatapadaobjekstring,list,tuple,dandictionary
dengansangatmudah.


21
SubrutinatauFungsi SubrutinatauFungsi SubrutinatauFungsi SubrutinatauFungsi
Dalam pemograman kadangkala suatu kode yang telah
ditulis harus dipanggil kembali dengan nilai yang berbeda. Solusi
akan hal ini adalah menggunakan subrutin atau fungsi. Fungsi
sendiriada2jenisyaknifungsidefaultdanfungsiyangbisadibuat
sendiri. Fungsi default atau dalam python dikenal dengan built-in
telah tersedia dalam bahasa pemograman seperti fungsi-fungsi
yang dijelaskan sebelumnya contohnya len, pow, abs, dll. Pada
bagian ini tidak menjelaskan fungsi-fungsi built-in, namun
mengenai cara pembuatan fungsi dan pemanggilannya. Semua
jenis bahasa pemograman mengenal statemen fungsi, termasuk
python. Pembuatan fungsi pada python selalu diawali dengan
sintakdefdandiikutinamafungsinya.Kemudianuntukmemanggil
fungsi tersebut cukup menyebutkan nama fungsi beserta
parameter pendukungnya bila ada. Berikut akan dijelaskan
deklarasifungsidanaturannyasecarabertahap:

>>> def cetak1():


... print 'hallo world'
...
>>> def cetak2(n):
... print n
...
>>> cetak1()
hallo world
>>> cetak2(123)
123
>>> cetak2('apa kabar?')
apa kabar

2fungsidiatasberbedapadaadatidaknyaparameterfungsi.

>>> def cetak3(x,y,z):


... print x,y,z
...
>>> def cetak4(x,y,z=4):
... print x,y,z
...
>>> cetak3(1,2,3)
1 2 3
>>> cetak4(1,2)
1 2 4

22
>>> cetak4(1,2,3)
1 2 3

Contohdiatasmenjelaskantentangpenggunaanparameter
berdasarkan posisi. Misalkan pemanggilan fungsi cetak3(1,2,3)
akansecaraotomatismemberikannilai1kex,2key,dan3kez.
Perbedaan dengan fungsi cetak4 adanya penyebutan nilai default
pada parameter tertentu yakni nilai z=4. Bila pemanggilannya
tanpa menyertakan nilai z tidak akan menimbulkan error karena z
telahmemilikinilaidefault.Sebagaicatatanpenyebutanparameter
dengan nilai default harus diletakkan di posisi belakang dalam
deklarasifungsi,contoh:

>>> def cetak4(x=4,y,z):


... print x,y,z
...
SyntaxError: non-default argument follows default
argument
>>> def cetak4(x,y=4,z):
... print x,y,z
...
SyntaxError: non-default argument follows default
argument
>>> def cetak4(y,z,x=4):
... print x,y,z
...
>>>

Penyebutan parameter dengan nilai default pada posisi awal atau


tengahakanmenimbulkanpesanerror.

>>> bil=10
>>> def ganti(bil):
... bil=100
...
>>> ganti(bil)
>>> bil
10
>>> kar='apa kabar'
>>> def ganti(kar):
... kar='hallo'
...
>>> ganti(kar)
>>> kar

23
'apa kabar'
>>> t=1,2,3
>>> def ganti(t):
... t[2]=10
...
>>> ganti(t)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 2, in ubah
TypeError: object does not support item assignment
>>> t
(1, 2, 3)
>>> l=[2,4.5,'a']
>>> def ganti(l):
... l[1]='ubah'
...
>>> l
[2, 4.5, 'a']
>>> ganti(l)
>>> l
[2, 'ubah', 'a']

Masihingattentangobjekmutabledanimmutable?Fungsidi
atas menjelaskan bahwa nilai parameter dapat diubah atau tidak,
kembali pada kedua sifat objek tersebut. Sebagai contoh
parameter bil, kar, dan t merupakan objek yang immutable
sehingga pemanggilan fungsi untuk mengubah nilai ketiga
parameter tidak berpengaruh. Lain halnya dengan parameter l,
sebagai list merupakan objek yang mutable. Disini fungsi dapat
melakukanperubahannilaiparameterl.

>>> bil=4000
>>> kar='apa kabar'
>>> t=1,4.5,30
>>> l=['a',5,'56']
>>> def ftup(*parameter):
... for x in parameter:
... print x,
...
>>> ftup(bil,t,l,kar)
4000 (1, 4.5, 30) ['a', 5, '56'] apa kabar

Contohdiatasmenggambarkankeistimewaanpythondalam
pembacaan paramater secara posisional dalam bentuk tuple.
Apapun parameter yang dimasukkan akan dibaca berdasarkan

24
indeksposisinya.

>>> def fdic(**param):


... for x in param.values():
... print x,
...
>>> fdic(nama='rido',umur=21,kuliah='amikom')
amikom 21 rido
>>> def fdic(**param):
... for x in param.keys():
... print x,':',param[x]
...
>>> fdic(nama='rido',umur=21,kuliah='amikom')
kuliah : amikom
nama : rido
umur : 21

Selain parameter posisi dalam bentuk tuple, python


menyediakan parameter berupa kata kunci dalam bentuk
dictionary. Contoh di atas mungkin cukup jelas untuk dipahami.
Pada umumnya suatu fungsi mengembalikan suatu nilai. Dalam
halinikatakunciyangdigunakanadalahreturn.

>>> def luas3(a,t):


... return 0.5*a*t
...
>>> luas3(4,7)
14.0

AturanLGB AturanLGB AturanLGB AturanLGB


Cobaperhatikankodeberikut:

>>> a='aku'
>>> def f():
... a='saya'
... print a
...
>>> print a
aku
>>> f()
saya


25
Dalam pemograman kadang pernah ditemukan nama
variabelyangsama.Tampakpadacontohdiatasterdapatvariabel
a dengan nilai 'aku', di samping itu variabel a juga terdapat pada
fungsif()dengannilai'saya'.Perbedaankeduanyaadalahvariabel
a di luar fungsi f() bersifat global sedangkan variabel a di dalam
fungsi f() bersifat lokal. Variabel lokal hanya berlaku untuk blok
tertentu dalam hal ini fungsi f() dan akan dihapus dari memori
setelahbloktersebutselesaidikejakan,sedangkanvariabelglobal
berlaku untuk semua. Dalam membaca suatu parameter, python
terlebih dahulu mencari secara lokal, bila tidak ditemukan akan
mencari secara global, dan terakhir akan mencari dalam built-ins.
Aturan semacam ini dikenal dengan sebutan LGB atau Lokal,
Global,Built-ins,sebagaicontoh:

>>> x1='ini global'


>>> def f():
... x2='ini lokal'
... print x1
... print x2
... print len(x1), len(x2)
...
>>> f()
ini global
ini lokal
10 9
>>> x1
ini global
>>> x2
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'x2' is not defined
>>> len(x1)
10
>>> len(x2)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'x2' is not defined

Karena variabel x1 bersifat global maka bisa dibaca pada


setiap blok kode. Sedangkan untuk variabel x2 hanya bisa dibaca
padablokfungsif().Perhatikanpadapenggunaanfungsilenyang
bersifatbuilt-ins.Sebenarnyasuatuvariabeldidalambloktertentu
bisadideklarasikansecaraglobaldenganmenggunakankatakunci

26
global,seperticontohberikut:

>>> def f():


... global x2
... x2='ini global juga'
... print x2
...
>>> f()
ini global juga
>>> print x2
ini global juga

Tampakbahwadeklarasivariabelx2didalamblokfungsif().
Dengankatakunciglobal,variabelinibersifatglobalsehinggabisa
dibaca pada setiap blok kode dengan catatan fungsi f() dipanggil
terlebihdahulu.

Eksepsi Eksepsi Eksepsi Eksepsi


Pemogramanyangbaiktidakmelupakanteknikpenanganan
kesalahan yang baik. Hal ini sangat berguna untuk dijadikan
sebagai acuan dalam kesempurnaan suatu aplikasi yang dibuat.
Penanganan kesalahan dalam pemograman dikenal dengan
sebutan eksepsi. Python sendiri telah melakukan penanganan
kesalahan dengan baik serta dilengkapi pesan kesalahan yang
cukup jelas sehingga sangat membantu programmer dalam
membangun suatu aplikasi. Bagian ini akan dijelaskan pesan-
pesan kesalahan yang dimiliki oleh python beserta teknik
penanganankesalahan.

Pesan-pesankesalahanyangterdapatdipython
Kesalahan Kesalahan Kesalahan Kesalahan Keterangan Keterangan Keterangan Keterangan
NameError

SyntaxError
TypeError

tidak ditemukan variabel setelah dicari


berdasaraturanLGB
kesalahanpenulisansintak
kesalahanoperasiterhadapobjekyangtidak
mendukung operasi tersebut misalkan
perubahannilaiobjekimmutable

27
Kesalahan Kesalahan Kesalahan Kesalahan Keterangan Keterangan Keterangan Keterangan
lOError
lndexError

KeyError

Keyboardlnterrupt

ValueError

ZeroDivisionError
kesalahanoperasiinput/output
kesalahan operasi indeksasi yang melebihi
batas
kesalahan pada dictionary saat pencarian
keyyangtidakditemukan
interupsi program oleh user, biasanya
penekanantombol^C
kesalahan penanganan argumen, misalkan
pemberiannilai0tigaparameterpadafungsi
range
adanyaoperasipembagiandengan0

Contoh:

>>> dir()
['__builtins__', '__doc__', '__name__', 'a', 'f',
'luas', 'x']
>>> g
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'g' is not defined
>>> for i in range(0,10)
File "<stdin>", line 1
for i in range(0,10)
^
SyntaxError: invalid syntax
>>> t=1,2,3
>>> t[2]=5
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: object does not support item assignment
>>> file=open('gaada')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
IOError: [Errno 2] No such file or directory: 'gaada'
>>> t[5]
Traceback (most recent call last):
File "<stdin>", line 1, in ?
IndexError: tuple index out of range
>>> D={'nama':'rido','umur':21}
>>> D['kelas']
Traceback (most recent call last):

28
File "<stdin>", line 1, in ?
KeyError: 'kelas'
>>> if x==1:
...(^C)
KeyboardInterrupt
>>> range(0,0,0):
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ValueError: range() step argument must not be zero
>>> 5/0
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ZeroDivisionError: integer division or modulo by zero

Contohdiatasmudah-mudahancukupjelasuntukdipahami.
Selanjutnyaadalahbagaimanateknikpenanganankesalahanyang
disediakan oleh python sehingga sesuai keinginan kita. Contoh
berikutmenampilkanmacam-macampenanganankesalahanyang
bisadigunakan:

>>> a=0
>>> b=2
>>> try:
... c=6/a
... print c
... except:
... print 'kesalahan pembagian dengan 0'
...
kesalahan pembagian dengan 0
>>> try:
... c=6/b
... print c
... except:
... print 'kesalahan pembagian dengan 0'
...
3
>>> try:
... c=6/b
... except:
... print 'kesalahan pembagian dengan 0'
... else:
... print c
...
3
>>> try:
... c=6/b

29
... print c
... finally:
... print 'selesai'
...
3
selesai
>>> try:
... c=6/a
... print c
... except ZeroDivisionError, pesan:
... print 'kesalahan : ',pesan
...
kesalahan : integer division or modulo by zero
>>> try:
... b=10
... try:
... print b/2
... except:
... print 'terjadi kesalahan'
... else:
... print 'tidak terjadi kesalahan'
... finally:
... print 'selesai'
...
5
tidak terjadi kesalahan
selesai
>>> pesan='terjadi kesalahan'
>>> isipesan='ini adalah isi pesan kesalahan'
>>> raise pesan
Traceback (most recent call last):
File "<stdin>", line 1, in ?
terjadi kesalahan
>>> raise pesan, isipesan
Traceback (most recent call last):
File "<stdin>", line 1, in ?
terjadi kesalahan: ini isi pesan kesalahan

Class Class Class Class


Python merupakan salah satu bahasa pemograman
berorientasi objek (OOP). Konsep OOP sangat membantu dalam
membuat aplikasi terutama yang berskala besar. Pada bagian
pembuatan aplikasi kita akan banyak menerapkan konsep OOP
dalamhaliniclass.Disiniakandijelaskanmengenaihal-halumum

30
mengenai OOP pada python dimana menurut penulis lebih
sederhana daripada di Java ataupun C++. Bentuk umum class di
pythonadalah:

class <nama_class>:
doc
data
fungsi

Docmengacupadadokumenstringyangmenjelaskansuatu
classdanbersifatopsional.Datadanfungsimungkinsudahdapat
pembacapahami.Agalebihmudahmemahamikitalangsungsaja
padacontohberikut:

>>> class profile:


... 'bagian ini hanya sebuah komentar'
... nama='rido'
... umur=21
... kampus='amikom'
... def f1(self):
... print 'fungsi1 di dalam class'
... def f2(self,n,u,k):
... print n,u,k
...
>>> instanprofile=profile()
>>> dir(instanprofile)
['__doc__', '__module__', 'f1', 'f2', 'kampus',
'nama', 'umur']
>>> instanprofile.nama
'rido
>>> instanprofile.f1()
fungsi1 di dalam class
>>> instanprofile.f2('eva',21,'amikom')
eva 21 amikom

Kata self berarti mengacu pada referensi suatu objek itu


sendiri, dalam contoh di atas adalah class profile beserta anggota
datanya. Objek hasil instansiasi, seperti instanprofile, bisa
ditambahkan anggota datanya setelah proses instansiasi dimana
tidak akan akan mengubah data-data pada class sumber.
Perhatikancontohberikut:

>>> class C:
... x=''

31
... def f1(self,s):
... self.x=s
...
>>> c=C()
>>> c.x
''
>>> c.f1('rido')
>>> c.x
'rido'
>>> instanprofile.a='tambahan'
>>> instanprofile.b=4400
>>> dir(instanprofile)
['__doc__', '__module__', 'a', 'b', 'f1', 'f2',
'kampus', 'nama', 'umur']
>>> dir(profile)
['__doc__', '__module__', 'f1', 'f2', 'kampus',
'nama', umur']

Bagi yang sudah mengenal OOP, pasti tahu adanya data


public dan private. Data public bisa diakses di setiap objek hasil
instansiasi suatu class. Sedangkan data private hanya bisa
diaksesolehanggotaclassnyasendiri.Pendeklarasiandataprivate
dipythondiawali2underscoredandiakhirimaksimal1underscore.
Berikutcontohnya:

>>> class oop:


... data1='data ini bersifat public'
... __data2='data ini bersifat private'
...
>>> x=oop()
>>> x.data1
'data ini bersifat public'
>>> x.data2
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: oop instance has no attribute 'data2'

Tampak objek (x) hasil instansiasi class oop tidak dapat


mengakses anggota data class yang bersifat private yakni
__data2. Sebenarnya di python tidak ada anggota private, yang
ada hanyalah pengalihan nama untuk anggota data tersebut.
Python melakukan pengalihan nama suatu data yang seolah-olah
bersifat private, contoh __data2, menjadi _oop__data2. Untuk
mengetahuinyalakukanperintahdir().

32
>>> dir(oop)
['__doc__', '__module__', '_oop__data2', 'data1']
>>> dir(x)
['__doc__', '__module__', '_oop__data2', 'data1']
>>> x._oop__data2
'data ini bersifat private'

Kadang kita menginginkan beberapa class dengan kondisi


yang mirip dengan 1 class sebagai class utama. Hal ini
berhubungan dengan konsep penurunan class atau inheritance
pada oop. Penurunan class akan membuat semacam class anak
yangakanmewarisianggotaclassutamaatauorangtuasertabisa
mengganti beberapa anggota data atau membuat baru sehingga
class anak ini lebih spesifik. Hal-hal yang bisa dijadikan pedoman
dalampenurunanclassadalah:
Class orang tua disebutkan dalam tanda kurung nama
classanak
Class anak akan mengambil semua anggota data class
orang tua yang berhak diambilnya bila class orang tua
masihmemilikiorangtuajuga
Penurunan class bisa dilakukan dari banyak orang tua
secaraberjenjangdengandipisaholehtandakoma
Bilaclassorangtuadananakmemilikinamaanggotadata
yangsama,makaanggotaclassanaklahyangberlaku.

>>> class oop:


... xoop='anggota oop'
... def foop(self):
... print xoop
...
>>> class oop1(oop):
... xoop1='anggota oop1'
... def foop1(self):
... print xoop1
...
>>> a=oop()
>>> b=oop1()
>>> dir(a)
['__doc__', '__module__', 'foop', 'xoop']
>>> dir(b)
['__doc__', '__module__', 'foop', 'foop1', 'xoop',
'xoop1']
>>> class oop2():

33
... xoop2='anggota oop2'
... def foop2(self):
... print xoop2
...
>>> class oop3(oop,oop2):
... def foop3(self):
... print 'hasil penurunan berjenjang'
...
>>> dir(oop2)
['__doc__', '__module__', 'foop2', 'xoop2']
>>> dir(oop3)
['__doc__', '__module__', 'foop', 'foop2', 'foop3',
'xoop', 'xoop2']
>>> class anak(oop3):
... def foop3(self):
... print 'fungsi di class anak'
...
>>> dir(anak)
['__doc__', '__module__', 'foop', 'foop2', 'foop3',
'xoop', 'xoop2']
>>> c=anak()
>>> c.foop3()
fungsi di class anak

Bagaimana membuat constructor dan destructor class pada


python? Dalam hal ini kita akan mengenal beberapa operator
overloading di python. Operator overloading adalah mengubah
tugas suatu operator dengan tugas baru, misalkan tanda + akan
bertugas menjumlahkan pada suatu operasi bilangan kemudian
padaoperasistringakanbertugassebagaipenggabungan.Berikut
tabeloperatoroverloadingyangberhubungandenganclass:

Operator Operator Operator Operator Keterangan Keterangan Keterangan Keterangan


__init__
__del__
__add__
__sub__
__or__
__repr__

__call__
__getattr__
constructor
destructor
penjumlahan
pengurangan
bitwiseor
konversi ke string dengan pasangan `` atau
pencetakan
pemanggilandalamfungsi
pengambilanatribut

34
Operator Operator Operator Operator Keterangan Keterangan Keterangan Keterangan
__getitem__
__setitem__
__getslice__
__len__
__cmp__
__radd__
pengambilanindeks
assignmentpadaindeks
irisan
nilaipanjang
perbandingan
penjumlahanobjekdisebelahkanan

Contoh:

>>> class oop:


... def __init__(self):
... print 'constructor class oop'
...
>>> class oop1(oop):
... def __init__(self):
... print 'constructor class oop1'
... oop.__init__(self)
...
>>> anak=oop1()
constructor class oop1
constructor class oop

Fungsi__init__akandijalankansecaraotomatisketikaadaproses
instansiasi. Bila terdapat penurunan class, maka constructor yang
akan dipanggil adalah dari class anak. Agar constructor bisa
dipanggil semua kita harus memanggilnya secara explisit pada
classanak.

>>> class oop:


... def __del__(self):
... print 'proses dealokasi data dari
memori'
...
>>> a=oop()
>>> dir(a)
['__del__', '__doc__', '__module__']
>>> del a
proses dealokasi data dari memori
>>> dir(a)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'a' is not defined

35
Fungsi ini akan dijalankan secara otomatis ketika suatu class
dihancurkan/dealokasi dari memori. Contoh di atas
mengilustrasikan suatu objek a (hasil instansiasi class oop) yang
dihancurkan dari memori dengan perintah del, maka akan
memanggil fungsi __del__ yang berfungsi sebagai destructor
class.

>>> class oop:


... jml=0
... def __add__(self,data):
... self.jml=self.jml+data
... print 'hasil penjumlahan=',self.jml
...
>>> anak=oop()
>>> anak+10
hasil penjumlahan=10
>>> class oop:
... jml=0
... def __sub__(self,data):
... self.jml=self.jml-data
... print 'hasil pengurangan=',self.jml
...
>>> anak=oop()
>>> anak-10
hasil pengurangan=-10

Fungsi __add__ dan __sub__ akan dipanggil ketika suatu objek


instansiasidiberioperasipenjumlahandanpengurangan.

>>> class oop:


... data1=0
... def __or__(self,data2):
... self.data1=self.data1|data2
... print 'nilai data=',self.data1
...
>>> anak=oop()
>>> anak|10
nilai data=10

Fungsi ini akan melakukan bitwise or pada objek yang dikenai


operasi|.

>>> class oop:


... data=10

36
... def __repr__(self,data):
... return `self.data
...
>>> anak=oop()
>>> anak.__repr__()+' hari'
'10 hari'
>>> anak.data+6
16
>>> anak
10

Tampak bahwa fungsi ini akan melakukan konversi ke tipe data


stringdanmelakukanpencetakan.

>>> class oop:


... data=10
... def __call__(self):
... print self.data
...
>>> anak=oop()
>>> anak
<__main__.O instance at 0x403f0e2c>
>>> anak()
10

Pemanggilanclassdilakukanlayaknyapemanggilanfungsikarena
adaoperatoroverloading__call__.

>>> class oop:


... def __getattr__(self,x):
... if x='atribut':
... print 'atribut class'
... else:
... print 'bukan atribut class'
...
>>> anak=oop()
>>> anak.f
bukan atribut class
>>> anak.atribut
atribut class

Fungsi ini akan dipanggil ketika kita mengakses nilai suatu atribut
class.


37
>>> class oop:
... data='hallo'
... def __getitem__(self,x):
... return self.data[x]
...
>>> anak=oop()
>>> for i in anak:
... print i,
...
h a l l o

Fungsi ini akan dipanggil setiap kita melakukan pengambilan


indekspadasuatuobjek.

>>> class oop:


... data=[]
... def __setitem__(self, indeks, nilai):
... self.data.append(nilai)
...
>>> anak=oop()
>>> anak.data
[]
>>> anak[0]=1
>>> anak[1]=2
>>> anak.data
[1, 2]
>>> oop.data
[1, 2]

Dengan adanya fungsi __setitem__, suatu objek seolah-olah


memiliki indeks dan kita bisa melakukan assignment pada indeks
objektersebut.

>>> class oop:


... data='hallo'
... def __getslice__(self,i,j):
... return self.data[i:j]
...
>>> anak=oop()
>>> anak[1:3]
'al'

Operator __getslice__ berguna untuk melakukan irisan dengan


mengambilnilaindeksdaridatasuatuobjek.


38
>>> class oop:
... data='hallo'
... def __len__(self):
... return len(self.data)
...
>>> anak=oop()
>>> len(anak)
5
>>> class oop:
... data=10
... def __cmp__(self,x):
... return cmp(self.data,x)
...
>>> anak=oop()
>>> anak<0
False
>>> anak==10
True
>>> class oop:
... jml=0
... def __radd__(self,x):
... return self.jml+x
...
>>> anak=oop()
>>> 5+anak
5
>>> anak+10
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: unsupported operand type(s) for +:
'instance' and 'int'

Penjelasam fungsi __len__, __cmp__, __radd__ mungkin


cukup jelas dari contoh yang diberikan. Sebenarnya kegunaan
__add__ dan __radd__ adalah sama yakni untuk penjumlahan.
Perbedaan keduanya adalah letak objek yang dikenai operasi
penjumlahan. Jika __add__ objeknya terletak di sebelah kiri
operator +, sedangkan __radd__ terletak di sebelah kanan
operator+.

Module Module Module Module


Module memiliki kegunaan yang sama dengan fungsi yakni
dalamhalpenggunaanulangkode-kodeprogramyangtelahditulis

39
sebelumnya. Perbedaannya adalah dalam hal lokasi, fungsi
tersimpanatauditulissecarainternaldidalamprogramyangdibuat
sedangkan module terdiri dari fungsi, class dan atribut lainnya
tersimpan dalam file eksternal. Selain itu cara pemanggilannya
jugamemilikiperbedaan,berikuttabelcarapemanggilanmodule:

Pemanggilan Pemanggilan Pemanggilan Pemanggilan Keterangan Keterangan Keterangan Keterangan


import<nama_module>

from<nama_module>import<fungsi>

from<nama_module>import*

reload(<nama_module>)

import<paket>.<nama_module>
memanggilmodule
secaradefault/apa
adanya
memanggilfungsidari
suatumodule
memanggilseluruh
atributsuatumodule
melakukanpemanggilan
kembalisuatumodule
memanggilmoduledari
suatupaket

Untuk membuat suatu module sama halnya seperti


menuliskan kode suatu program yang berisi berbagai variabel,
dokumentasi,fungsi,class,dsblaludisimpandalamfileberektensi
.py.Selanjutnyauntukmelakukanpemanggilanmoduleyangtelah
dibuat cukup meng-import nama file tersebut tanpa ektensi. Jadi
jika kita membuat module dengan nama file tesmodule.py, maka
untuk meng-importnya nama modulenya menjadi tesmodule.
Beberapa hal yang berhubungan dengan module adalah sebagai
berikut:
Segala hal dalam python selalu berhubungan dengan
module, termasuk saat berada dalam lingkungan interaktif
pythonkitamenggunakanmodule__main__:

>>> dir()
['__builtins__', '__doc__', '__name__']
>>> __name__
'__main__'

File module bisa berupa script di luar python misalkan


dalambentukC

40
PencarianmoduleberdasarkanlokasiPATHPYTHON
Dalam melakukan pemanggilan, antara nama module dan
atributnyadipisahkanolehtandatitik(.).
Module pada dasarnya akan dijalankan layaknya script
pythonlainnya
Pythonakanmengcompilemoduledenganektensi.pysaat
pertama kali di-import kemudian akan menghasilkan file
berektensi .pyc yang akan dijalankan setiap kali module
tersebut di-import lagi. Hal ini untuk mempercepat waktu
pembacaansuatumodule.

Contoh:

lsifilemodule1.py:

'ini komentar dari module'


nama='rido'

def f1():
print 'nama:',nama,'umur:',umur

Modusinteraktif:

>>> import module1


>>> dir(module1)
['__builtins__', '__doc__', '__file__', '__name__',
'f1', 'nama']
>>> module1.nama
'rido'
>>> module1.f1()
nama: rido
>>> module1.__doc__
'ini komentar dari module'

lsifilemodule2.py,contohberikutmengilustrasikanbahwamodule
jugadieksekusilayaknyascript:

print 'ini baris pertama'


nama='rido'

def f2():
print nama

41
print 'ini baris terakhir'

Modusinteraktif:

>>> import module2


ini baris pertama
ini baris terakhir
>>> dir(module2)
['__builtins__', '__doc__', '__file__', '__name__',
'f2', 'nama']

Contohberikutmengilustrasikanpemanggilanmoduledalam
caralaindengantetapmenggunakanmodule2.Sebelumnyakeluar
dari modus interaktif (CTRL+D) dan masuk kembali untuk
merefresh.

>>> dir()
['__builtins__', '__doc__', '__name__']
>>> from module2 import *
ini baris pertama
ini baris terakhir
>>> dir()
['__builtins__', '__doc__', '__name__', 'f2', 'nama']
>>> ^D

>>> from module2 import f2
>>> dir()
['__builtins__', '__doc__', '__name__', 'f2']
>>> f2()
rido
>>> del f2
>>> from module2 import f2 as fungsi2
>>> dir()
['__builtins__', '__doc__', '__name__', 'fungsi2']

Coba perhatikan perbedaan antara pemanggilan module


secara default pada contoh sebelumnya dengan contoh di atas.
Tampak setelah kita melakukan perintah dir(), pada pemanggilan
default yang ditampilkan adalah nama modulenya sedangkan
pemanggilandenganmenggunakanatributyangditampilkanbukan
nama modulenya melainkan hanya atribut yang dipanggil dengan
catatan jika * memanggil seluruh atribut yang ada. Selanjutnya
akan diberikan contoh penggunaan fungsi reload yang berfungsi

42
membukadanmembacaulangisimodule.

lsifilemodule3.pysebelumperubahan:

isi='ini adalah isi module sebelum perubahan'

Modusinteraktif:

>>> import module3


>>> print module3.isi
ini adalah isi module sebelum perubahan

lsifilemodule3.pysetelahperubahan:

isi='ini adalah isi module setelah perubahan,


memanggilnya dengan reload'

Modusinteraktif:

>>> print module3.isi


ini adalah isi module sebelum perubahan
>>> import module3
>>> print module3.isi
ini adalah isi module sebelum perubahan
>>> reload(module3)
<module 'module3' from '/usr/lib/python2.4/module3.py'>
>>> print module3.isi
ini adalah isi module setelah perubahan, memanggilnya
dengan reload

Setelahdilakukanperubahanisifilemodule3.py,atributyang
dibacatetappadaisimoduleyanglamaterbuktipadakasusdiatas
saatkita melakukan operasi pencetakan denganprint outputyang
ditampilkanadalahnilaidariatributisimodulesebelumperubahan.
Dibagianlainkitajugamelakukanimportyangkeduakalidengan
harapanpythonakanmembacakembalimodule3,namunhasilnya
sama saja. Hal ini membuktikan bahwa python hanya melakukan
import satu kali dalam satu proses. Jadi untuk mendapatkan nilai
terbarudarisuatumodulekitamelakukanreload(module3).
Pythonjugamendukungpengelompokanmoduledalamsatu
paket. Paket yang dimaksud berhubungan dengan direktori
pengelompokan module-module. Berikut langkah-langkah

43
membuatsuatupaketmodule:
Sebelumnyakitaharusmembuatsuatudirektoriyangakan
menjadinamapaket
Di dalam direktori tersebut dibutuhkan suatu file dengan
nama __init__.py sebagai inisialisasi atau penanda suatu
paket dimana isinya bisa berupa dokumen, variabel, atau
kosong.
Membuat module yang akan digunakan dan disimpan
dalamdirektoriyangtelahdibuat
Contohberikutdengannamapaket/direktoripaket1:

lsifile__init__.py:

'inisialisasi paket1'

Dari module-module yang telah dibuat, dipindahkan pada direktori


paket1denganperintahmv:

# mv module1.py paket1
# mv module2.py paket1
# mv module3.py paket1

Modusinteraktif:

>>> import paket1


>>> dir(paket1)
['__builtins__', '__doc__', '__file__', '__name__',
'__path__']
>>> paket1.__doc__
'inisialisasi paket1'
>>> import paket1.module2
ini baris pertama
ini baris terakhir
>>> dir(paket1.module2)
['__builtins__', '__doc__', '__file__', '__name__',
'f2', 'nama']
>>> import paket1.module3
>>> paket1.module2.nama
'rido'

Python menyediakan module yang bermacam-macam baik


sederhana hingga yang komplek. Pembuatan module baru harus

44
disesuaikan oleh kebutuhan, jika pada python telah tersedia
alangkahbaiknyamenggunakanyangtelahada.

lnputdanOutput lnputdanOutput lnputdanOutput lnputdanOutput


Dalam buku ini hanya akan dijelaskan sedikit penggunaan
operasi input dan output pada python. Operasi input yang umum
digunakan adalah raw_input() dan print untuk operasi outputnya.
Penerapannyasangatmudah,ikuticontohberikut:

>>> a=raw_input('nama:')
nama:

Perintah raw_input() akan meminta masukanatau input dalam hal


ini dari keyboard. Kasus di atas dapat dijelaskan hasil input yang
diterimaakandisimpankedalamvariabela.

nama:rido
>>> a
'rido'

>>> print a
rido

Kadangkala kita menginginkan suatu operasi input tanpa echo


sepertiinputpassword.Pythonmenyediakansebuahmoduleyang
berhubungandenganhaliniyaitugetpass.

>>> import getpass


>>> password=getpass.getpass()
Password:
>>> password
'rhs'
>>> password=getpass.getpass('Masukkan password anda: ')
Masukkan password anda:
>>> password
'rahasia'


45
OperasiFile OperasiFile OperasiFile OperasiFile
Menggunakan suatu file di python bisa dengan berbagai
modus,secaragarisbesarmodusyangdimaksudadalahbacadan
tulis. Sama seperti aturan umum dalam penggunaan file yaitu
membuka file dengan modus tertentu dan jika telah selesai
disarankanuntukmenutupkembalifiletersebut.Berikutkodedari
moduspenggunaanfile:
r :modusuntukmembaca
rb :modusuntukmembacafilebinary
w :modusuntukmenulis
wb :modusuntukmenulisfilebinary
a :modusuntukmenambahkanisifiledibagianakhir
ab :modusuntukmenambahkanisifilebinary

Jika file yang ingin dibuka dengan modus membaca tidak


ditemukanakanmenimbulkanerror.Jikafileyangdibukandengan
modus menulis atau menambah tidak ditemukan, maka akan
dibuat secara otomatis. Untuk melakukan pembukaan dengan
modus membaca dan menulis secara simultan, maka tambahkan
tanda+ pada modus. Selanjutnya beberapa operasi file yang bisa
dilakukanadalah:
open(file,modus):untukmembukafile
close():untukmenutupfile
read(jmlstring):membacaisifile,jikajumlahtidakdiisikan
akanmembacaseluruhisifile
readline(jmlstring):membacafilesecaraperbaris
seek(posisi):memindahkanposisipembacaanisifile
write(string):menuliskedalamfile

Contoh:

>>> a=open('nofile','r')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
IOError: [Errno 2] No such file or directory: 'xx'
>>> a=open('nofile','r')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
IOError: [Errno 2] No such file or directory: 'nofile'

46
>>> a=open('/home/buku/profile_client.py','r')
>>> b=open('nofile','w')
>>> c=open('/home/buku/profile_client.py','a')
>>> d=open('nofile','w+')
>>> a.read()
'#/usr/bin/python\nimport xmlrpclib\n\nprint "Masukkan
data anda :\\n"\nnip = raw_input("N I M : ")\nnama =
raw_input("Nama : ")\njabatan = raw_input("Jabatan :
")\ngol = raw_input("Golongan : ")\n\n\'\'\' Koneksi ke
server \'\'\'\npegawai =
xmlrpclib.Server(\'http://172.16.0.1:3000\')\n\n\'\'\'
Menyimpan data pegawai
\'\'\'\nt=pegawai.Simpan(nip,nama,jabatan,gol)\nprint
t\n'
>>> a.seek(0)
>>> a.read(30)
'#/usr/bin/python\nimport xmlrpc'
>>> a.seek(0)
>>> a.readline()
'#/usr/bin/python\n'
>>> b.write('ini file yang dibuat secara otomatis')
>>> b.read()
Traceback (most recent call last):
File "<stdin>", line 1, in ?
IOError: [Errno 9] Bad file descriptor
>>> d.read()
'ini file yang dibuat secara otomatis'
>>> c.write('ini baris tambahan')
>>> a.read()
'import xmlrpclib\n\nprint "Masukkan data anda
:\\n"\nnip = raw_input("N I M : ")\nnama =
raw_input("Nama : ")\njabatan = raw_input("Jabatan :
")\ngol = raw_input("Golongan : ")\n\n\'\'\' Koneksi ke
server \'\'\'\npegawai =
xmlrpclib.Server(\'http://172.16.0.1:3000\')\n\n\'\'\'
Menyimpan data pegawai
\'\'\'\nt=pegawai.Simpan(nip,nama,jabatan,gol)\nprint
t\nini baris tambahan'
>>> a.close()

Dalam beberapa kasus, kadang suatu program perlu


menuliskan data sementara ke dalam suatu file. Setelah program
selesai, maka file tersebut akan dihapus. Python menyediakan
moduleuntukhaliniyaitutempfile,berikutcontohnya:


47
>>> import tempfile
>>> temp=tempfile.TemporaryFile()
>>> data='ini sebuah file temporary'
>>> temp.write(data)
>>> temp.seek(0)
>>> temp.read()
'ini sebuah file temporary'

OperasiWaktu OperasiWaktu OperasiWaktu OperasiWaktu


Untuk operasi waktu python menyediakan sangat banyak
fungsiyangterdapatdalammoduletime.Pythonmembacaformat
tahun dalam 2 digit, jadi jika tahun 70-88 secara otomatis dibaca
tahun 1970-1988 dan 0-25 secara otomatis akan dibaca 2000-
2025.HalinimengacupadaaturanPOSlXatauX/OPENstandard.
lstilah-istilahyangberhubungandenganwaktuyaitu:
epoch, suatu titik dimana suatu waktu dimulai, pada
lingkungan UNlX epoch adalah 1 Januari 1970 pukul
00:00:00waktuUTC.
UTC, singkatan dari Coordinated Universal Time, lebih
dikenaldenganistilahGreenwichMeanTime(GMT)
DST, Daylight Saving Time, merupakan suatu
penyesuaian zona waktu yaitu selisih waktu 1 jam dari 1
tahun

TipedatawaktudiUNlXsesuailibraryCadalahlonginteger
dengan jangkauan maksimum 2
31 -
1 detik atau sekitar
2.147.483.647 detik. Jika dalam 1 tahun diambil rata-rata
31.536.000 detik, maka bisa dihitung rata-rata jangkauan waktu
dari epoch adalah 2.147.483.647 / 31.536.000 = 68 tahun. Jadi
masa waktu terakhir adalah sampai 1970 + 68 = 2038, suatu isu
yangsangatbermasalahdiUNlX.
Beberapafungsiuntukmengambilwaktu:
time.time(), mengembalikan jangka waktu sejak epoch
hinggasaatinidalamsatuandetik
time.localtime(),mengembalikanwaktulokaldalambentuk
tuple
time.gmtime(), mengembalikan waktu UTC dalam bentuk
tuple

48
time.asctime(), mengembalikan waktu saat ini dalam
format'haribulantanggaljam:menit:detiktahun'
time.ctime(),samasepertiasctime()

Contoh:

>>> import time


>>> time.time()
1162228302.430162
>>> time.localtime()
(2006, 10, 30, 17, 11, 52, 0, 303, 0)
>>> time.gmtime()
(2006, 10, 30, 17, 12, 9, 0, 303, 0)
>>> time.asctime()
'Mon Oct 30 17:12:33 2006'
>>> time.ctime()
'Mon Oct 30 17:12:47 2006'


49
XMLRPC XMLRPC XMLRPC XMLRPC
Pernah dengar isitilah distributed system atau komputer
klaster (=cluster) atau superkomputer? Bagi dunia lT isitilah ini
mungkin sudah tidak asing lagi. Tapi sekedar intro tidak ada
salahnya akan dijelaskan sedikit teori yang ada hubungannya
denganistilahtersebut.
Distributed System atau yang lebih dikenal dengan sebutan
komputer klaster merupakan penggabungan beberapa sistem
(dalam hal ini berhubungan dengan komputer) yang saling
berkontribusi dalam menyelesaikan suatu masalah terhubung
dalam suatu jaringan baik lokal maupun internet dengan catatan
terdapat pembagian tugas untuk setiap alamat. Komputer klaster
merupakan suatu solusi alternatif penggunaan superkomputer
yangharganyasangatmahaldanterbatasproduksinya.
Teknologi distributed system terdiri dari beberapa kategori
diantaranya:
Socket, sangat cocok jika ingin membuat semacam
protokolbaru
Remote Procedure Call (RPC) seperti Sun RPC, SOAP,
XMLRPC
Object terdistribusi dalam satu bahasa pemograman
seperti Java Remote Method lnvocation (RMl), DOPY,
Pyro
Object terdistribusi tanpa memperdulikan perbedaan
bahasapemogramansepertiDCOM,CORBA
dan teknologi lainnya seperti Message-oriented
middleware,mobileagent

Dalam pembahasan kali ini kita akan melakukan


implementasi distributed system dalam sebuah pemograman
menggunakan bahasa python. Berdasarkan kategori yang
dijelaskan, python menyediakan teknologi default untuk Remote
Procedure Call yakni module XMLRPC. Pada teknologi RPC,
interaksidilakukandenganpemanggilanprocedureataufungsidan
membutuhkanmodelpengalamatanserver,protokoltransport,dan

50
typemarshalling.Teknologiinitelahdipertimbangkansekitartahun
1976. Pada XMLRPC, pengalamatan server dan protokolnya
menggunakan HTTP serta XML sebagai type marshallingnya.
Python telah menyediakan 2 module untuk masing-masing sub-
systemyaknixmlrpclibuntuksisiclientdanSimpleXMLRPCServer
disisiserver.Berikutdiberikancontohpenggunaankeduamodule
tersebutpadabeberapaaplikasi.
Contoh aplikasi ini berupa simulasi sederhana aplikasi
database(padakasusinipenulismenggunakan2komputerdalam
1jaringanlokal),langkah-langkahnya:
membuat skrip yang berisi beberapa fungsi pada sisi
server
menjalankan aplikasi melalui modus interaktif pada sisi
client

lsifileprofile_server.pyberisifungsi-fungsi:

import SimpleXMLRPCServer

class Profile:
def __init__(self):
'''
Overloading Konstruktor Class Profile
'''
self.profile = []

def Simpan(self, nip, nama, jabatan, gol):
'''Register Data Profile dengan
mengembalikan nilai nip'''
reg=list([nip,nama,jabatan,gol])
self.profile.append(reg)
return nip

def Cari(self,nip):
'''Mencari Data Profile berdasar
nilai nip'''
info='gagal'
for i in self.profile:
if i[0]==nip:
info=i
break
return info



51
server = SimpleXMLRPCServer.SimpleXMLRPCServer
(('172.16.0.1',3000))
server.register_instance(Profile())
server.serve_forever()

Di sisi client kita menjalankan aplikasinya melalui modus


interaktif. Pada kasus ini alamat komputer server adalah
172.16.0.1 dan alamat komputer client 172.16.0.2 (mengenai
jaringan secara detail tidak akan dibahas disini demi membatasi
masalah:-D).Berikutcaramenjalankanaplikasidisisiclient:

>>> import xmlrpclib


>>> pegawai=xmlrpclib.Server('http://172.16.0.1:3000')
>>> pegawai.Simpan('1','rido','kepsek','IVB')
'1'
>>> pegawai.Simpan('2','novriana','guru','IIIB')
'2'
>>> pegawai.Cari('1')
['1', 'rido', 'kepsek', 'IVB']
>>> pegawai.Cari('2')
['2', 'novriana', 'guru', 'IIIB']

Daricontohdiatasdapatdijelaskanlangkah-langkahpemograman
terdistribusimenggunakanteknologiXMLRPCsebagaiberikut:
melakukanimportmoduleSimpleXMLRPCServerpadasisi
server
membuat fungsi-fungsi yang akan dipanggil pada sisi
server
melakukan register sever berupa penentuan alamat
jaringan dan port yang akan digunakan pada proses
distribusi, dalam contoh di atas ('172.16.0.1',3000) serta
registerclassserver.
menjalankan aplikasi server yang telah dibuat, cara
menjalankan sama halnya menjalankan aplikasi python
pada umumnya (perhatikan kembali C-1. Menjalankan
Python).
menjalankan aplikasi client dengan terlebih dahulu
melakukanimportmodulexmlrpclib
melakukan koneksi ke server, pada contoh
pegawai=xmlrpclib.Server('http://172.16.0.1:3000')
memanggil method-method atau fungsi-fungsi yang telah

52
disediakandiserver

Contoh di atas sebenarnya masih ada kekurangannya


terutama disaat kita melakukan operasi CTRL+C pada aplikasi
server. Maka ketika menjalankan kembali kadang muncul pesan
socket.error yang mengatakan bahwa alamat sedang digunakan.
Selain itu, pada aplikasi tersebut belum ada filter alamat yang
diperbolehkan mengakses. Untuk itu pada aplikasi berikut akan
melakukan perbaikan pada aplikasi server di atas, ikuti langkah
berikut:
TambahkanmodulesocketdansebelumclassProfile,
tambahkanskripberikut:

import socket

class ProfileXMLRPCServer
(SimpleXMLRPCServer.SimpleXMLRPCServer):
def __init__(self, *args):
'''
Constructor
'''
SimpleXMLRPCServer.SimpleXMLRPCServer.
__init__(self, (args[0], args[1]))
self.ACCESSLIST = (
'172.16.0.2', '127.0.0.1',
)

def server_bind(self):
'''
Server bind...
'''
self.socket.setsockopt
(socket.SOL_SOCKET,
socket.SO_REUSEADDR, 1)
SimpleXMLRPCServer.SimpleXMLRPCServer.
server_bind(self)

def verify_request(self, request,
client_address):
'''
Filtering IP pada ACCESSLIST
'''
if client_address[0] in self.ACCESSLIST:
return 1
else:

53
return 0

Padabagianakhirgantibagian:

server = SimpleXMLRPCServer.SimpleXMLRPCServer
(('172.16.0.1',3000))

menjadi:

server = ProfileXMLRPCServer('172.16.0.1',3000)

DariskripdiataskitamembuatclassProfileXMLRPCServer
yang merupakan turunan dari class SimpleXMLRPCServer
sehinggaaplikasimampumenggunakanportsecaraberulangdan
melakukan filetering alamat tertentu. Sekarang coba jalankan
kembali aplikasi servernya dan lakukan hal-hal seperti
sebelumnya. Lalu bandingkan dengan melakukan penekanan
tombol CTRL+C dan perubahan lP pada sisi client, apa yang
terjadi? Berikut contoh satu lagi penggunaan module xmlrpclib,
dengan tetap berpedoman pada aplikasi di atas tetapi dari sisi
clientlebihaplikatif:

lsifileprofile_client.py:

import xmlrpclib

print "Masukkan data anda :\n"
nip = raw_input("N I M : ")
nama = raw_input("Nama : ")
jabatan = raw_input("Jabatan : ")
gol = raw_input("Golongan : ")

''' Koneksi ke server '''
pegawai = xmlrpclib.Server('http://172.16.0.1:3000')

''' Menyimpan data pegawai '''
t=pegawai.Simpan(nip,nama,jabatan,gol)
print t

Selanjutnya coba jalankan aplikasi server dan clientnya


pada masing-masing komputer. Pada kasus ini data yang kita
inputkan akan disimpan dalam sebuah buffer memory, jadi ketika

54
kita keluar dari modus interaktif atau aplikasi selesai dijalankan
dataakanhilangsecaraotomatis.

PYGRESQL PYGRESQL PYGRESQL PYGRESQL


PyGreSQL merupakan suatu paket aplikasi untuk module
koneksi database PostgreSQL. Pada instalasi python secara
default,moduleinitidaktersedia.Olehkarenaitu,perlumelakukan
download paket. Penulis mendapatkan paket ini di URL
http://www.pygresql.org atau bisa juga bertanya pada google
sebagai alternatif. Paket yang penulis dapatkan berupa source
berektensi .tgz untuk distribusi slackware. Sebelumnya kita harus
memiliki aplikasi PostgreSQL yang terinstall pada komputer.
Berikut akan dijelaskan dari awal instalasi hingga penerapannya
pada aplikasi. Untuk kemudahan penulis sertakan paket-paket
yangberhubunganpadaCD.

lnstalasidanKonfigurasiPostgreSQL lnstalasidanKonfigurasiPostgreSQL lnstalasidanKonfigurasiPostgreSQL lnstalasidanKonfigurasiPostgreSQL


PaketaplikasiPostgreSQLbisadidapatkandisitusresminya
http://www.postgresql.org atau mirror lain. Langkah-langkah
instalasiPostgreSQL(berupasource)adalahsebagaiberikut:
Unpackpaket

# tar -xjpvf postgresql-8.0.3.tar.bz2


# cd postgresql-8.0.3

Konfigurasi(gunakanopsi-opsiyangdisesuaikandengan
kebutuhan)

# ./configure --prefix=/usr/local/pgsql
--enable-FEATURE=yes --with-python --with-openssl
--with-libraries=/lib:/usr/lib --with-zlib
--with-include=/usr/include --with-gnu-ld


55
Kompilasidansetup

# make; make install

Membuatuserpostgres(bilaperlugrouppostgresjuga)

# groupadd postgres
# adduser postgres

Membuat direktori untuk inisialisasi database PostgreSQL


misalkan "data pada direktori prefix dan mengubah hak
kepemilikannyakepadauserdangrouppostgres

# mkdir /usr/local/pgsql/data
# chown -R postgres.postgres /usr/local/pgsql/data

MelakukaninisialisasidatabasePostgreSQLdengan
statususerpostgres

# su postgres
# /usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data

MenjalankanPostgreSQL MenjalankanPostgreSQL MenjalankanPostgreSQL MenjalankanPostgreSQL


Pada umumnya skrip-skrip pemanggilan service diletakkan
pada direktori /etc/rc.d (pada distribusi Slackware, untuk lainnya
tinggal menyesuaikan) seperti /etc/rc.d/rc.httpd untuk service
apache, /etc/rc.d/rc.mysqld untuk service mysql, dsb. Berikut
contoh sederhana skrip pemanggilan service untuk PostgreSQL
dengannamarc.pgsql:

#!/bin/sh
# Scripts untuk start dan stop PostgreSQL
server=/usr/local/pgsql/bin/postmaster
pgctl=/usr/local/pgsql/bin/pg_ctl
data=/usr/local/pgsql/data
case "$1" in
start)
echo "Menjalankan PostgreSQL..."
su - postgres -c "$server -i -D $data
>logfile 2>&1 &"

56
echo -n ""
;;
stop)
echo -n "Menghentikan PostgreSQL..."
su - postgres -c "$pgctl -D $data stop"
;;
restart)
echo -n "Mengulang PostgreSQL..."
su - postgres -c "$pgctl -D $data restart"
;;
status)
su - postgres -c "$pgctl -D $data status"
;;
*)
echo "Gunakan: `basename $0`
(start|stop|restart|status)"
exit 1
;;
esac
exit 0

Setelahkitamembuatskripnya,jadikanfiletersebutsebagai
fileyangdapatdieksekusidenganperintahberikut:

# chmod 744 /etc/rc.d/rc.pgsql

Sekarangkitabisamencobaskriptersebut,jalankansalahsatu
dariperintahberikut:
1.MenjalankanPostgreSQL

# /etc/rc,d/rc.pgsql start

2.MengulangPostgreSQL

# /etc/rc.d/rc.pgsql restart

3.MenghentikanPosgreSQL

# /etc/rc.d/rc,pgsql stop

4.MelihatapakahPostgreSQLsedangaktifatautidak

# /etc/rc.d/rc.pgsql status


57
Jika kita ingin menjalankan PostgreSQL secara otomatis
saat proses booting sistem, maka kita perlu menambahkan skrip
berikutpadafile/etc/rc.d/rc.M:

if [ -x /etc/rc.d/rc.pgsql ]; then
. /etc/rc.d/rc.pgsql start
fi

Selanjutnya kita juga bisa membuat file konfigurasi yang


berisi PATH dari PostgreSQL seperti library, manual, data, dan
binarinya. File ini berguna sekali saat user melakukan perintah-
perintah pada lingkungan PostgreSQL, kita hanya mengetikkan
perintahnyasecaralangsungtanpaharusdiikutiunsurdirektorinya
misalnya jika kita menjalankan perintah
"/usr/local/pgsql/bin/createdb hanya tinggal mengetikkan
"createdb. Direktori lokasi inisialisasi PATH adalah /etc/profile.d,
dengan file inisialisasi misal pgsql.sh dengan isinya sebagai
berikut:

#!/bin/sh
# Variable - Variable PostgreSQL
dir=/usr/local/pgsql
lib=$dir/lib
library_path=$lib:$library_path
manpath="$MANPATH:$dir/man"
data=$dir/data
PATH="$PATH:$dir/bin"
export dir
export lib
export library_path
export manpath
export data
export PATH


MembuatDatabase MembuatDatabase MembuatDatabase MembuatDatabase
Pembuatan database dilakukan oleh user postgres atau
user lain yang diberi izin oleh user postgres. Untuk mendaftarkan
user (misal rido) sebagai user PostgreSQL baru juga dilakukan
olehpostgresdanuseryangdiberihakdenganperintahberikut:


58
# su postgres
pg$ createuser rido
Shall the new user be able...database? (y/n) y
Shall the new user be able...new users? (y/n) n
CREATE USER
pg$ exit
# exit

Berdasarkan perintah di atas, user rido hanya diberi hak
untuk membuat database tanpa hak membuat user baru.
Selanjutnya user rido dapat membuat database (misal database
tuxhouse)denganperintah:

$ createdb tuxhouse

Jikaberhasil,untukmelakukankoneksikedatabasetuxhou tuxhou tuxhou tuxhouse se se se


lakukanperintahberikut:

$ psql -d tuxhouse
Welcome to psql 8.0.3, the PostgreSQL interactive
terminal.

Type: \copyright for distribution terms
\h for help with SQL commands
\? for help with psql commands
\g or terminate with semicolon to execute query
\q to quit

tuxhouse=>

Kita sekarang telah berada pada server database tuxhouse


dan bisa melakukan perintah-perintah SQL. Untuk menambahkan
sistem keamanan database kita bisa memberikan password untuk
userdatabasedenganmetodeenkripsiMD5.

# su rido
$ psql -d tuxhouse
...
tuxhouse=> alter USER rido with encrypted password
'rahasia';




59
QueryDatabase QueryDatabase QueryDatabase QueryDatabase
Untuk mengisi database ada dua cara yang dapat kita
lakukanyaitucaralangsung(mengetikkanperintah-perintahSQL
padaserverdatabase)dantidaklangsung(pemanggilanfile),cara
kedua lebih disarankan karena kita akan mempunyai referensi
penulisandatabasenya.Sebelumnyakitaharusmembuatfileyang
berisitag-tagquery,berikutcontohisidarifiletuxhouse:

create table pegawai(


nip char(15) not null,
nama_pegawai varchar(40) not null,
alamat varchar(50),
tmp_lahir varchar(20),
tgl_lahir date,
jk boolean,
agama char(1),
pendidikan char(1),
jabatan char(1) not null,
gol char(1) not null,
status char(1),
tgl_masuk date,
constraint pegawai_pk primary key (nip));

Setelahdisimpan,kembalimasukkedatabasetuxhousedan
lakukanperintahberikut:

tuxhouse=> \i tuxhouse

Perintah "\i adalah salah satu perintah dalam PostgreSQL


untuk memanggil (download) suatu file. PostgreSQL telah
mengenal perintah TAB-Completion yaitu kemampuan
menyempurnakanmasukanperintahdenganmenekantombolTAB
misalnya kita ingin memasukkan perintah create, create, create, create, dapat dilakukan
dengan menuliskan cr+TAB cr+TAB cr+TAB cr+TAB dan secara otomatis tulisan perintah
akan melengkapi sendiri. Bahasa query PostgreSQL telah
mengikuti standar SQL, berikut perintah DDL dan DML yang
berhubungandenganquerydatabasesecaragarisbesar:

Untukmengisidata:

insert into <nama tabel> values(<data tiap kolom>)



60
insert into <nama tabel> (<pilihan kolom>) values
(<data pilihan kolom>)

insert into pegawai values('130402675', 'rido',
'pejaten', 'jember', '1985-09-27', 't', 0, 6, 13, 13,
0, '2006-06-06', 0);
insert into pegawai (nip, nama, alamat, tmplahir,
tgllahir, jk, agama, pnddkn, jabatan, gol, status,
tglmasuk, ket) values('130402675', 'rido', 'pejaten',
'jember', '1985-09-27', 't', 0, 6, 13, 13, 0,
'2006-06-06', 0);

Untukmemanggildanmenampilkandata:

select <pilihan kolom> from <nama tabel> {| where


kondisi}
select * from <nama tabel> {| where kondisi}

select nama,alamat from pegawai;
select nama,alamat from pegawai where where
nip='130402675';
select * from pegawai;

Untukmelakukanupdatedata:

update <nama tabel> set <nama kolom>=<data kolom>


where <nama kolom>=<data kolom>

update pegawai SET nama='mahdi ridho',alamat=
'bondowoso' where nip='130402675';

Untukmenghapusdata:

delete from <nama tabel> {| where kondisi}


truncate <nama tabel>

delete from pegawai;
delete from pegawai where nip='130402675';
truncate pegawai;

lnstalasidanKonfigurasiPy lnstalasidanKonfigurasiPy lnstalasidanKonfigurasiPy lnstalasidanKonfigurasiPyg gg greSQL reSQL reSQL reSQL


Untukmelakukaninstalasilangkahnyasangatmudahyaitu:
Lakukanperintahinstallpkgdenganstatususerroot:

61
# installpkg PyGreSQL.tgz

Perintah di atas akan menghasilkan direktori /PyGreSQL-


3.8.1 (kebetulan versi yang digunakan adalah 3-8-1).
Selanjutnyabisadibacafileinstall.txtpadadirektoridocdi
dalamdirektoriPyGreSQL-3.8.1ataubagiyangtidakingin
pusing-pusingbisaikutinlangkahberikut:

# python setup.py build


# python setup.py install

Sebelum menjalankan perintah di atas, service PostgreSQL harus


dalam keadaan aktif. Perintah di atas untuk melakukan kompilasi
kemudian mengkopikan beberapa file library ke direktori
/usr/lib/python2.4/site-packages.

Selanjutnya kita akan mengenalkan library PostgreSQL


dengan cara membuat link dengan nama libpq.so.4 yang
mengarahpadafile/usr/local/pgsql/lib/libpq.so.4.0.Filelink
iniakandisimpandalamdirektori/usr/lib.Halinidilakukan
karena berdasar percobaan kasus yang penulis lakukan,
ketika python melakukan import module database
PostgreSQL muncul pesan yang mengatakan tidak
menemukan file libpq.so.4. Padahal file tersebut
sebenarnya telah ada, namun lokasi yang dimaksudkan
tidak sesuai. Untuk membuat file link tersebut lakukan
perintahberikut:

# ln -s /usr/local/pgsql/lib/libpq.so.4.0
/usr/lib/libpq.so.4

Sampai disini kita sudah bisa melakukan koneksi database


PostgreSQLdaripython.Sekedarujicobaikutiperintahberikut:

>>> import pg
>>> db=pg.DB('tuxhouse','localhost',5432,None,None,
'rido','rahasia')

Selanjutnya akan dijelaskan hal-hal yang berhubungan


dengan module, koneksi, query, definisi data, dsb yang disajikan

62
dalamcontoh-contohaplikasidatabasedenganpython.

ModuleDatabasePostgreSQL ModuleDatabasePostgreSQL ModuleDatabasePostgreSQL ModuleDatabasePostgreSQL


Dari hasil installasi di atas menghasilkan 2 nama module
untukkoneksidatabasePostgreSQLyaitu_pgdanpg.2moduleini
memilikikarakteristikyangsedikitberbedanamunberfungsisama.
Pada bagian ini penulis hanya akan membahas penggunaan
module pg. Ada alasan kuat mengapa pilihan jatuh pada module
pgyaitupenanganandatabaseyangcukupmudah,banyakfungsi-
fungsi yang mendukung, dan sangat sesuai dengan karakteristik
python. Namun penulis juga tidak memaksa jika anda memiliki
pilihan lain. Untuk mempelajari dokumentasi module bisa melalui
modusinteraktifpython,caranyadenganbantuanperintahhelp():

>>> help()
help> modules
help> _pg
.......
help> pg
.......

Perintah modules untuk menampilkan informasi module-


module yang didukung oleh python. Untuk menampilkan
dokumentasi dari module-module yang ada cukup dengan
mengetikkannamamodulenya,misalkan_pg,pg,time,dsb.Menu
help() ini sangat membantu sekali bagi anda terutama penulis
dalamprosesbelajar.

KoneksiDatabase KoneksiDatabase KoneksiDatabase KoneksiDatabase


Dalam melakukan koneksi terdapat beberapa atribut yang
harus disebutkan sebagai informasi yang berhubungan dengan
databasediantaranya:
dbname : namadatabase,isianberupadatastringatau
None
host : alamatdatabaseserver,isianberupadata
stringatauNone

63
port :nomorportdatabaseserverdefaultnya5432,
isianberupadataintegeratau-1
opt :opsikoneksi,isianberupadatastringatauNone
tty : terminalyangdigunakanbiasanyauntukdebug,
isianberupadatastringatauNone
user : userdatabase,isianberupadatastringatau
None
passwd :passworduserdatabase,isianberupadata
stringatauNone

Hasil dari pemanggilan koneksi ini akan mengembalikan suatu


objek koneksi yang bernama pgobject. Berikut contoh melakukan
koneksi:

>>> import pg
>>> konek1=pg.DB(dbname='tuxhouse',host='localhost',
user='rido',passwd='rahasia')
>>> konek2=pg.DB('tuxhouse','localhost',5432,None,
None,'rido','rahasia')

Untuk mengulang koneksi ke database gunakan fungsi


reset(), sedangkan untuk menghentikan atau menutup koneksi
gunakanfungsiclose().

>>> konek1.reset()
>>> konek1.close()

Query Query Query Query


Penulissangatkagumdenganpenerapanfungsiquerypada
modulepg,seakan-akankitasedangmelakukankoneksilangsung
dengan database server. Fungsi query telah mendukung semua
operasiDDLmaupunDML.Jadicukupdenganfungsiinikitasudah
bisamelakukansegalamacamoperasiquery,berikutcontohnya:

>>> import pg
>>> konek=pg.DB('tuxhouse','localhost',5432,None,
None,'rido','rahasia')
>>> konek.query(select * from pegawai)
...

64
>>> konek.query(delete from pegawai where nama='fdfs'")
...
>>> konek.query("insert into pegawai values
('312333423', 'hari', 'lampung', 'jogja', '1998-9-9',
'f', 3, 4, 1, 1, 1, '2005-8-8', 2)")
17664L
>>> konek.query("update pegawai set alamat='jogja',
tmplahir='lampung' where nama='hari'")
>>> konek.query(create table tes(isi char(5)))
>>> konek.query("drop table tes")
>>> konek.query("create view tes as select nama,
alamat from pegawai")
>>> konek.query("drop view tes")
>>> konek.query("alter user rido with encrypted
password 'secret'")

Sebelumnya pernah disinggung bahwa karakteristik module


pg sangat sesuai dengan karakteristik python. Untuk mengetahui
hal ini penulis akan memberikan contoh dari hasil penggunaan
fungsiqueryberikut:

>>> a=konek.query(select * from pegawai)


>>> dir(a)
['dictresult', 'fieldname', 'fieldnum', 'getresult',
'listfields', 'ntuples']

Hasiloperasiquerydiatasdisimpankedalamvariabela.Perintah
dir(a) berfungsi untuk menampilkan atribut-atribut yang ada pada
variabeladimana,berikutpenjelasandarimasing-masingatributdi
atas:
dictresult,methoduntukmenampilkanhasilqueryselect
dalambentuklistdictionary
fieldname,methoduntukmenampilkannamakolom
tertentu
fieldnum,methoduntukmenampilkannomorkolom
tertentu
getresult,methoduntukmenampilkanhasilqueryselect
dalambentuklisttuple
listfields,methoduntukmenampilkansemuanamakolom
dalambentuktuple
ntuples,methoduntukmenampilkanjumlahrecorddata
hasilqueryselect

65
Untuklebihjelasnyaperhatikancontohberikut:

>>> a.dictresult()
[{'status': '1', 'nama': 'pipit', 'ket': '1', 'gol': '0
', 'jabatan': '0 ', 'tmplahir': 'jogja', 'tglmasuk':
'2006-07-07', 'jk': 'f', 'tgllahir': '1984-07-06',
'nip': '130402676', 'pnddkn': '7 ', 'alamat':
'temanggung', 'agama': '2 '}, {'status': '2', 'nama':
'agung nugroho', 'ket': '2', 'gol': '4 ', 'jabatan': '4
', 'tmplahir': 'jogja', 'tglmasuk': '2002-09-02', 'jk':
't', 'tgllahir': '1982-06-06', 'nip': '130402677',
'pnddkn': '5 ', 'alamat': 'jogja', 'agama': '3 '},
{'status': '0', 'nama': 'mahdi ridho', 'ket': '0',
'gol': '13', 'jabatan': '13', 'tmplahir': 'jember',
'tglmasuk': '2006-06-06', 'jk': 't', 'tgllahir': '1985-
09-27', 'nip': '130402675', 'pnddkn': '6 ', 'alamat':
'bondowoso', 'agama': '0 '}, {'status': '1', 'nama':
'hari', 'ket': '2', 'gol': '1 ', 'jabatan': '1 ',
'tmplahir': 'lampung', 'tglmasuk': '2005-08-08', 'jk':
'f', 'tgllahir': '1998-09-09', 'nip': '312333423',
'pnddkn': '4 ', 'alamat': 'jogja', 'agama': '3 '}]
>>> a.dictresult()[0]
{'status': '1', 'nama': 'pipit', 'ket': '1', 'gol': '0
', 'jabatan': '0 ', 'tmplahir': 'jogja', 'tglmasuk':
'2006-07-07', 'jk': 'f', 'tgllahir': '1984-07-06',
'nip': '130402676', 'pnddkn': '7 ', 'alamat':
'temanggung', 'agama': '2 '}
>>> a.dictresult()[0]['nama']
'pipit'
>>> a.dictresult()[2]['nip']
'130402675'

>>> a.fieldname(2)
'alamat'
>>> a.fieldnum('nama')
1

>>> a.getresult()
[('130402676', 'pipit', 'temanggung', 'jogja', '1984-07-
06', 'f', '2 ', '7 ', '0 ', '0 ', '1', '2006-07-07',
'1'), ('130402677', 'agung nugroho', 'jogja', 'jogja',
'1982-06-06', 't', '3 ', '5 ', '4 ', '4 ', '2', '2002-
09-02', '2'), ('130402675', 'mahdi ridho', 'bondowoso',
'jember', '1985-09-27', 't', '0 ', '6 ', '13', '13',
'0', '2006-06-06', '0'), ('312333423', 'hari', 'jogja',
'lampung', '1998-09-09', 'f', '3 ', '4 ', '1 ', '1 ',
'1', '2005-08-08', '2')]

66
>>> a.getresult()[1]
('130402677', 'agung nugroho', 'jogja', 'jogja', '1982-
06-06', 't', '3 ', '5 ', '4 ', '4 ', '2', '2002-09-02',
'2')
>>> a.getresult()[1][3]
'jogja'

>>> a.listfields()
('nip', 'nama', 'alamat', 'tmplahir', 'tgllahir', 'jk',
'agama', 'pnddkn', 'jabatan', 'gol', 'status',
'tglmasuk', 'ket')
>>> a.listfields()[3]
'tmplahir'

>>> a.ntuples()
4

Method-method di atas akan sangat berguna saat kita


membuat aplikasi database yang banyak melakukan operasi
query. Oleh karena itu, disarankan pahami benar masalah
penggunaanlist,tuple,dandictionary.

Method Method Method Method- -- -MethodKoneksi MethodKoneksi MethodKoneksi MethodKoneksi


Objek koneksi yang telah dibuat sebenarnya memiliki
banyak method yang sangat berguna bagi kita. Dengan
tersedianya bermacam method ini, objek koneksi seakan-akan
dapat mengendalikan database server sepenuhnya. Beberapa
methodyangdimaksudadapadatabelberikut:

Method Method Method Method Keterangan Keterangan Keterangan Keterangan


pkey(tabel)

get_databases()

get_relations(opsi)

Mengembalikaninformasiprimarykey
suatutabel
Mengembalikaninformasisemuadatabase
yangadadalambentuklist
Mengembalikanlistinformasirelasidalam
database.Opsi-opsiyangbisadigunakan
yaitur=tabelbiasa,i=index,S=sequence,
v=view,c=compositetype,s=spesial,
t=tabelTOAST.Jikaopsitidakdiisikan

67
Method Method Method Method Keterangan Keterangan Keterangan Keterangan

get_tables()

get_attnames(tabel)

get(tabel,a,b)

insert(tabel,a)

update(tabel,a)

delete(tabel,a)
akanmenampilkansemuarelasiyangada
Mengembalikanlistinformasitabeldalam
database
Mengembalikaninformasiatributsuatu
tabeldalambentukdictionary
Mengembalikandictionarysuatubaristabel
dengananilaikolomdanbnamakolom,
berfungsidalamoperasipencariansuatu
data
Queryinsertdatakesuatutabeldengana
berupadictionarydata
Queryupdatedatakesuatutabeldengana
berupadictionarydata
Querydeletedatakesuatutabeldengana
berupadictionarydata

Contoh:

>>> konek.pkey('pegawai')
'nip'
>>> konek.get_databases()
['tuxhouse', 'kepegawaian', 'template1', 'template0']
>>> konek.get_relations()
['information_schema.applicable_roles',
'information_schema.check_constraints',
'information_schema.column_domain_usage',
'information_schema.column_privileges',
'information_schema.column_udt_usage',
'information_schema.columns',
'information_schema.constraint_column_usage',
'information_schema.constraint_table_usage',
'information_schema.data_type_privileges',
'information_schema.domain_constraints',
'information_schema.domain_udt_usage',
'information_schema.domains',
'information_schema.element_types',
'information_schema.enabled_roles',
'information_schema.information_schema_catalog_name',
'information_schema.key_column_usage',
'information_schema.parameters',
'information_schema.referential_constraints',

68
'information_schema.role_column_grants',
'information_schema.role_routine_grants',
'information_schema.role_table_grants',
'information_schema.role_usage_grants',
'information_schema.routine_privileges',
'information_schema.routines',
'information_schema.schemata',
'information_schema.sql_features',
'information_schema.sql_implementation_info',
'information_schema.sql_languages',
'information_schema.sql_packages',
'information_schema.sql_sizing',
'information_schema.sql_sizing_profiles',
'information_schema.table_constraints',
'information_schema.table_privileges',
'information_schema.tables',
'information_schema.triggered_update_columns',
'information_schema.triggers',
'information_schema.usage_privileges',
'information_schema.view_column_usage',
'information_schema.view_table_usage',
'information_schema.views', 'public.absensi',
'public.mutasi', 'public.mutasi_pk', 'public.pegawai',
'public.pegawai_pk', 'public.promosi',
'public.promosi_pk', 'public.terminasi',
'public.terminasi_pk']
>>> konek.get_relations('r')
['information_schema.sql_features',
'information_schema.sql_implementation_info',
'information_schema.sql_languages',
'information_schema.sql_packages',
'information_schema.sql_sizing',
'information_schema.sql_sizing_profiles',
'public.absensi', 'public.mutasi', 'public.pegawai',
'public.promosi', 'public.terminasi']
>>> konek.get_relations('i')
['public.mutasi_pk', 'public.pegawai_pk',
'public.promosi_pk', 'public.terminasi_pk']
>>> konek.get_tables()
['information_schema.sql_features',
'information_schema.sql_implementation_info',
'information_schema.sql_languages',
'information_schema.sql_packages',
'information_schema.sql_sizing',
'information_schema.sql_sizing_profiles',
'public.absensi', 'public.mutasi', 'public.pegawai',
'public.promosi', 'public.terminasi']
>>> konek.get_attnames('pegawai')

69
{'status': 'text', 'gol': 'text', 'pnddkn': 'text',
'nama': 'text', 'tmplahir': 'text', 'jabatan': 'text',
'oid': 'int', 'tglmasuk': 'date', 'jk': 'bool',
'tgllahir': 'date', 'agama': 'text', 'ket': 'text',
'alamat': 'text', 'nip': 'text'}
>>> konek.get('pegawai','130402675','nip')
{'status': '0', 'gol': '13', 'pnddkn': '6 ', 'nama':
'mahdi ridho', 'jabatan': '13', 'tmplahir': 'jember',
'tglmasuk': '2006-06-06', 'oid(public.pegawai)': 17625L,
'tgllahir': '1985-09-27', 'agama': '0 ', 'ket': '0',
'alamat': 'bondowoso', 'nip': '130402675', 'jk': 't'}
>>> konek.insert('pegawai',{'status': '0', 'gol': '13',
'pnddkn': '6 ', 'nama': 'arie', 'jabatan': '13',
'tmplahir': 'jember', 'tglmasuk': '2006-06-06',
'tgllahir': '1985-09-27', 'agama': '0 ', 'ket': '0',
'alamat': 'bondowoso', 'nip': '123456', 'jk': 't'})
{'status': '0', 'gol': '13', 'ket': '0',
'oid(public.pegawai)': 17672L, 'nama': 'arie',
'jabatan': '13', 'jk': 't', 'tglmasuk': '2006-06-06',
'tmplahir': 'jember', 'tgllahir': '1985-09-27', 'agama':
'0 ', 'pnddkn': '6 ', 'alamat': 'bondowoso', 'nip':
'123456 '}
>>> konek.update('pegawai',{'status': '0', 'gol': '13',
'pnddkn': '6 ', 'nama': 'arie kurniawan', 'jabatan':
'13', 'tmplahir': 'purwokerto', 'tglmasuk': '2006-06-
06', 'tgllahir': '1985-09-27', 'agama': '5 ', 'ket':
'0', 'alamat': 'medan', 'nip': '123456', 'jk': 't'})
{'status': '0', 'gol': '13', 'ket': '0',
'oid(public.pegawai)': 17672L, 'nama': 'arie kurniawan',
'jabatan': '13', 'jk': 't', 'tglmasuk': '2006-06-06',
'tmplahir': 'purwokerto', 'tgllahir': '1985-09-27',
'agama': '5 ', 'pnddkn': '6 ', 'alamat': 'medan', 'nip':
'123456 '}
>>> konek.delete('pegawai',{'status': '0', 'gol': '13',
'pnddkn': '6 ', 'nama': 'arie kurniawan', 'jabatan':
'13', 'tmplahir': 'purwokerto', 'tglmasuk': '2006-06-
06', 'tgllahir': '1985-09-27', 'agama': '5 ', 'ket':
'0', 'alamat': 'medan', 'nip': '123456', 'jk': 't',
'oid(public.pegawai)': 17672L})

Pada contoh insert perhatikan bagian oid(public.pegawai),


data ini semacam nomor urut data yang diinsertkan dalam type
long. Nilai dari oid ini secara otomatis diisikan oleh database
server. Method update akan membaca primary key suatu tabel
sebagai index kondisi, biasanya dalam sintak SQL berupa where.
Berbeda saat melakukan method delete, disini kita harus

70
menyertakan data oid yang akan dihapus karena yang akan
dijadikanindexkondisiadalahnilaidarioidsetiapbarisdata.
Dari contoh di atas kita dihadapkan pada 2 pilihan dalam
melakukan query insert, update, dan delete. Dalam hal ini penulis
lebih menyarankan untuk menggunakan cara pertama yakni
methodquerykarenalebihmudahdanfleksibel.
Selanjutnya kita akan bermain dengan contoh aplikasi
database sederhana yang berisi fungsi-fungsi pengolahan
database seperti simpan, hapus, ubah, dan cari. Sebelumnya
buatlahsebuahtabelbarudengannamaprofile:

create table profile(


nim char(15) not null,
nama varchar(40) not null,
alamat varchar(50),
umur integer,
constraint profile_pk primary key (nim));

Kemudianbuatlahbeberapafiledengankodesebagaiberikut:

lsifilesimpan.py:

import pg

class Profile:
def __init__(self):
self.profile = ''

def Simpan(self,nim,nama,alamat,umur):
db=pg.DB('tuxhouse','localhost',
5432,None,None,'rido','rahasia')
try:
s=1
db.get('pegawai',nim,'nim')
except:
s=0
if s==1:
pesan='data sudah ada'
else:
db.query("insert into profile
values ('"+nim+"', '"+nama+"',
'"+alamat+"', "+umur+")")
pesan='data berhasil disimpan'
db.close()

71
return pesan;

print "Masukkan data anda :\n"
nim = raw_input("N I M : ")
nama = raw_input("Nama : ")
alamat = raw_input("Alamat : ")
umur = raw_input("Umur : ")

profile=Profile()
p=profile.Simpan(nim,nama,alamat,umur)
print p

lsifileubah.py:

import pg

class Profile:
def __init__(self):
self.profile = ''

def Ubah(self,cnim,nim,nama,alamat,umur):
db=pg.DB('tuxhouse','localhost',
5432,None,None,'rido','rahasia')
try:
s=1
db.get('profile',cnim,'nim')
except:
s=0
if s==0:
pesan='data tidak ada'
else:
db.query("update profile set
nim='"+nim+"', nama='"+
nama+"', alamat='"+alamat+"',
umur="+umur+" where nim='"+
cnim+"'")
pesan='data berhasil diubah'
db.close()
return pesan;

cnim = raw_input("Masukkan NIM lama : ")
nim = raw_input("NIM baru : ")
nama = raw_input("Nama baru: ")
alamat = raw_input("Alamat baru: ")
umur = raw_input("Umur baru: ")

profile=Profile()

72
p=profile.Ubah(cnim,nim,nama,alamat,umur)
print p

lsifilehapus.py:

import pg

class Profile:
def __init__(self):
self.profile = ''

def Hapus(self,nim):
db=pg.DB('tuxhouse','localhost',
5432,None,None,'rido','rahasia')
try:
s=1
db.get('profile',nim,'nim')
except:
s=0
if s==0:
pesan='data tidak ada'
else:
db.query("delete from profile
where nim='"+nim+"'")
pesan='data berhasil dihapus'
db.close()
return pesan;

nim = raw_input("Masukkan NIM : ")

profile=Profile()
p=profile.Hapus(nim)
print p

lsifilecari.py:

import pg

class Profile:
def __init__(self):
self.profile = ''

def Cari(self,nim):
db=pg.DB('tuxhouse','localhost',
5432,None,None,'rido','rahasia')
try:

73
s=1
a=db.get('profile',nim,'nim')
except:
s=0
if s==0:
print 'data tidak ada'
else:
print 'NIM:',a['nim']
print 'Nama:',a['nama']
print 'Alamat:',a['alamat']
print 'Umur:',a['umur']
db.close()

nim = raw_input("Masukkan NIM : ")

profile=Profile()
p=profile.Cari(nim)

GUlPYTHON GUlPYTHON GUlPYTHON GUlPYTHON


Seorang teman pernah bertanya, "Apa bisa kita melakukan
pemograman visual dengan Python? Bagi anda yang sudah
terlanjur belajar python pasti memiliki pikiran seperti itu. Python
merupakan salah satu bahasa scripting yang kaya akan module,
termasuk untuk pemograman visual. Kenyataan memang
membuktikan tampilan menjadi salah satu daya tarik yang kuat
bagi suatu aplikasi. Kini python telah mendukung banyak module
dalam hal pemograman visual, sebut saja PyGTK, PyQT, dan
Tkinter. Untuk installasi python dari paket distribusi belum
menyediakanmodule-moduleini,jadikitaperlumelakukanupdate
atau penambahan module secara manual. Kali ini penulis akan
membahas module PyGTK atau GTK dari awal installasi sampai
penerapannya dalam beberapa aplikasi. Dan pada akhir
pembahasan kita akan membuat suatu aplikasi database secara
komplekmenggunakaninterfaceGTKdanPostgreSQL.


74
PYGTK PYGTK PYGTK PYGTK
Bagi yang pernah menggunakan GLADE, kata GTK+ pasti
sudah tidak asing. GTK+ merupakan sebuah library untuk
pemograman Graphical User lnterfaces (GUl) dengan arsitektur
berorientasi pada bahasa C. GTK+ telah dapat bekerja di semua
lingkungan UNlX maupun Windows. Licensinya berada dalam
naungan GNU Library General Public License (GNU LGPL),
sehingga bersifat open source dan free. Sampai saat ini telah
dikembangkan untuk dapat berjalan bersama dengan bahasa lain
termasuk C++, Objective-C, Guile/Scheme, Perl, Python, TOM,
Ada95, Free Pascal, dan Eiffel. Untuk distribusi Python disebut
PyGTK, module yang satu ini bisa didapatkan melalui homepage
resminya di http://www.pygtk.org. Dengan PyGTK, kita bisa
melakukan pemograman GTK ala python. Apakah PyGTK telah
mendukung banyak widget atau tampilan window dan seberapa
bagustampilannya?Silahkanandaberipenilaiansendiridaritabel
widgetberikut:

GambarWidget GambarWidget GambarWidget GambarWidget Keterangan Keterangan Keterangan Keterangan

GtkAccelLabel, objek label


yang ditampilkan bersama
tombolacceleratordisebelah
kanantekslabel

GtkButton,objektombolyang
menerimansignalketika
diklik

GtkCheckButton,menerima
signalketikakotakdipilih
ataudicek





75

GtkColorButton,tombol
untukmenjalankandialog
pilihanwarna

GtkColorSelectionDialog,
dialogboxuntukpilihan
warna

GtkComboBoxEntry,objek
untukmasukantextdalam
bentuklistmenurun

GtkComboBox,objekyang
digunakanuntukmemilih
itemyangada

GtkEntry,objekuntuk
menerimamasukanberupa
singletext

GtkFileChooserButton,
tomboluntukmenjalankan
pilihanfile









76

GtkFontButton, tombol untuk


menjalankan pilihan font dari
dialog

GtkFileChooserDialog,
bergunadalammelakukan
operasiFilesepertiOpendan
Save

GtkFontSelectionDialog,
dialogboxuntukmemilihfont

GtkLabel,objekuntuk
menampilkantekslabel

GtkFrame,objekbingkai
denganoptionallabel






77

GtklconView,widgetuntuk
menampilkanlisticondi
dalamsebuahgrid

GtkTreeView,widgetyang
berfungsimenampilkandata
dalambentuklistatautree

Gtklmage,widgetuntuk
menampilkangambar

GtkMenuBar,objekmenu
item

GtkMessageDialog,objek
untukmenampilkanpesan







78

GtkTextView,widgetyang
menerimamasukanteks
sebanyak-banyaknya

GtkNotebook,biasadikenal
dengansebutantabbed

GtkProgressBar,widgetyang
menghitungjalannyasuatu
prosesdalambentukvisual

GtkSpinButton,objekyang
mengembalikannilaiinteger
ataufloat

GtkStatusBar,memberikan
pesanataupunketerangan
pentingkepadauser
biasanyadiletakkandibawah
suatuaplikasi







79

GtkPaned,objekpanes
secarahorizontaldanvertikal

GtkRadioButton,objekuntuk
memilihsatudarisuatugroup
pilihan

GtkScale,objekuntuk
merubahukuransecara
horizontaldanvertikal

GtkScrolledWindow,widget
untukscrollatas-bawahdan
kanan-kiri




80

GtkSeparator,widgetuntuk
garisbatassecarahorizontal
danvertikal

GtkWindow,objekutamadi
levelatas,semuaobjekakan
diletakkandisini

GtkToggleButton,tombol
yangmenerimasignaldari
statusnya

GtkToolbar,untukmembuat
toolbar

Secara pribadi penulis berpendapat widget-widget yang


disediakan oleh GTK sudah cukup untuk digunakan dalam
membuat suatu aplikasi biasa maupun profesional. Hal ini
diperkuat dengan alasan bahwa GTK merupakan bahasa standar
yang digunakan dalam membangun desktop GNOME serta
aplikasi pendukungnya. Pada pembahasan kali ini penulis tidak
akan membahas keseluruhan widget di atas. Penulis membatasi
pada widget-widget umum yang sering dipakai dan berhubungan





81
dengan aplikasi yang nantinya akan dibuat. Namun dari contoh-
contoh aplikasi yang dibuat anda diharapkan mampu
menggunakanwidgetlainnyayangtidakdijelaskandisini.

GtkWindow GtkWindow GtkWindow GtkWindow


Widget ini merupakan bagian pertama yang harus dibuat
karena semua objek akan diletakkan disini. Ada banyak method
untuk mengatur properti, namun penulis hanya akan menjelaskan
beberapamethodyangumumdigunakandiantaranya:
set_title,memberipropertijudulataucaption
get_title,mengembalikannilaicaption
set_position,menentukanposisiwindowsaatpertamakali
dieksekusi
set_focus,meletakkan/menfokuskankursorpadasuatu
widget
set_resizable,menentukankeadaanukuranyangdinamis
resize,mengaturukuranlebardantinggi
set_sensitive,mengaturkeadaanenableataudisable
set_border_width,mengaturukuranborder
show,menampilkanobjeknyasendiridalamhaliniwidget
window
show_all,menampilkanseluruhwidgetyangadadalam
window

Contoh:

>>> a=gtk.Window()
>>> a.set_title('Contoh Window')
>>> a.get_title()
'Contoh Window'
>>> a.set_position(gtk.WIN_POS_CENTER_ALWAYS)
>>> a.set_resizable(True)
>>> a.resize(200,200)
>>> a.set_border_width(10)
>>> a.show()
>>> gtk.main()


82

Perhatikan pada baris kode terakhir terdapat kode


gtk.main(). Kode ini akan melakukan pemanggilan fungsi utama.
Segala objek yang telah dibuat pada dasarnya akan dikirim ke
fungsi utama ini. Ketika objek a diberi method show(), maka akan
dikirim terlebih dahulu ke fungsi utama. Jadi objek a tidak akan
tampil sebelum kita menjalankan fungsi utama. Berikut contoh
dalamsebuahfile:

#!/usr/bin/python

import gtk

class window(gtk.Window):
def __init__(self, parent=None):
gtk.Window.__init__(self)
try:

self.set_screen(parent.get_screen())
except AttributeError:
self.connect('destroy',
lambda *w: gtk.main_quit())

self.set_title("Contoh Window")
self.set_border_width(10)
self.set_resizable(True)
self.resize(200,200)
self.set_position(gtk.WIN_POS_CENTER)
self.show()

if __name__ == '__main__':
window()
gtk.main()

83
Pertama-tama dibuat sebuah class pembuatan widget
window, kemudian ketika program dijalankan python akan selalu
memanggil atribut utama yaitu __main__. Selanjutnya dari
statemen if program akan memanggil class window. Pengaturan
posisipadawindowada5yaitu:
gtk.WlN_POS_NONE
gtk.WlN_POS_CENTER
gtk.WlN_POS_MOUSE
gtk.WlN_POS_CENTER_ALWAYS
gtk.WlN_POS_CENTER_ON_PARENT

Kodeconnectpadabagianpenanganankesalahanberfungsi
untuk menerima signal dari user seperti menutup window. Ada 2
cara menutup window yaitu dengan menggunakan method
gtk.main_quit() dan destroy(). Jika menggunakan gtk.main_quit()
program akan mengakhiri program dengan menutup seluruh
window yang ada. Sedangkan destroy() sama halnya juga
mengakhiri program tapi sebatas window yang diberi signal
tersebut. Untuk lebih jelasnya penulis akan membuat 2 window
dengan2methoddiatas.

#!/usr/bin/python

import gtk

class window1(gtk.Window):
def __init__(self, parent=None):
gtk.Window.__init__(self)
try:

self.set_screen(parent.get_screen())
except AttributeError:
self.connect('destroy',
lambda *w: gtk.main_quit())

self.set_title("Contoh Window1")
self.show()

class window2(gtk.Window):
def __init__(self, parent=None):
gtk.Window.__init__(self)
try:

84
self.set_screen(parent.get_screen())
except AttributeError:
self.connect('destroy',
lambda *w: self.destroy())

self.set_title("Contoh Window2")
self.show()

if __name__ == '__main__':
window1()
window2()
gtk.main()

Cobajalankanprogramdiataslalulakukanpenutupanpada
masing-masingwindowdenganmenekantombolsilangdisebelah
pojokkananatas.Tampakperbedaannyabukan?

GtkFrame GtkFrame GtkFrame GtkFrame


Beberapamethodyangumumdigunakanpadawidgetini
adalah:
set_label,memberilabelpadaframe
get_label,mengembalikannilailabelframe
set_label_widget,memberilabelframedengannilaidari
sebuahwidgetGtkLabel
set_label_align,mengaturposisix,ylabelframedengan
posisiantara0.0s/d1.0
set_shadow_type,mengaturtypebayanganframe

Contoh:

#!/usr/bin/python

import gtk

class frame(gtk.Window):
def __init__(self, parent=None):
gtk.Window.__init__(self)
try:

self.set_screen(parent.get_screen())
except AttributeError:

85
self.connect('destroy',
lambda *w: gtk.main_quit())
self.set_title("Contoh Penggunaan
Frame")
self.resize(400,400)
box=gtk.VBox()
a=gtk.Frame()
b=gtk.Frame()
a.set_label('Frame 1')
label=gtk.Label('Frame 2')
b.set_label_widget(label)
a.set_label_align(0.0,0.5)
b.set_label_align(0.5,0.5)
a.set_shadow_type(gtk.SHADOW_IN)
b.set_shadow_type(gtk.SHADOW_OUT)
box.pack_start(a, padding=5)
box.pack_start(b, padding=5)
self.add(box)
self.show_all()

if __name__ == '__main__':
frame()
gtk.main()


86
Dalam meletakkan beberapa widget ke dalam window, kita
butuh sebuah objek bernama GtkBox yang dibagi menjadi dua
yaitu GtkHBox dan GtkVBox. GtkHBox akan menyusun widget-
widget secara horizontal, sebaliknya GtkVBox akan menyusun
secaravertikal.Parameterpaddingberfungsiuntukmengaturspasi
antara widget. Untuk menyusun widget-widget ke dalam Box
digunakan method pack_start. Perhatikan perbedaan properti
antara kedua frame yang dibuat, untuk macam-macam type
shadowantaralain:
gtk.SHADOW_NONE
gtk.SHADOW_lN
gtk.SHADOW_OUT
gtk.SHADOW_ETCHED_lN
gtk.SHADOW_ETCHED_OUT

GtkEntry GtkEntry GtkEntry GtkEntry


Method-methodyangbisadigunakan:
set_text,mengisikantext
set_visibility,jikabernilaiFalseakanmenyembunyikan
karakterdengankarakter*
set_invisible_char,menentukankarakterunicode
set_max_length,menentukanpanjangkarakteryangbisa
dimasukkan
set_width_chars,menentukanlebartextentry
set_sensitive,menentukankeadaanenableataudisable
set_alignment,menentukanposisitextdimulaidari0.0s/d
1.0

Contoh:

#!/usr/bin/python

import gtk

class entry(gtk.Window):
def __init__(self, parent=None):
gtk.Window.__init__(self)
try:

87
self.set_screen(parent.get_screen())
except AttributeError:
self.connect('destroy',
lambda *w: gtk.main_quit())
self.set_title("Contoh Penggunaan
Text Entry")
self.set_border_width(10)
vbox1=gtk.VBox()
vbox2=gtk.VBox()
hbox=gtk.HBox()
frame=gtk.Frame()
frame.add(vbox2)
hbox.pack_start(vbox1, padding=5)
hbox.pack_start(frame, padding=5)
text1=gtk.Entry()
text2=gtk.Entry()
text3=gtk.Entry()
text4=gtk.Entry()
text1.set_width_chars(20)
text1.set_max_length(5)
text2.set_text('terisi otomatis')
text2.set_sensitive(False)
text1.set_width_chars(10)
text2.set_alignment(0.5)
text3.set_visibility(False)
text3.set_invisible_char('#')
text4.set_visibility(False)
vbox1.pack_start(text1,False,False,5)
vbox1.pack_start(text2,False,False,5)
vbox2.pack_start(text3,False,False,5)
vbox2.pack_start(text4,False,False,5)
self.add(hbox)
self.show_all()

if __name__ == '__main__':
entry()
gtk.main()


88
Perhatikan method pack_start pada objek box, pada
dasarnyaparameteryangdimasukkanadalah(widget,expand,fill,
padding). Jika nilai expand adalah True, maka area box akan
dibagi secara seimbang. Fill berhubungan dengan dimensi setiap
widget di dalam box. Dan padding berfungsi dalam pengaturan
spasiantarawidget.

GtkComboBox GtkComboBox GtkComboBox GtkComboBox


PyGTK menyediakan 3 model ComboBox yang memiliki
sedikit perbedaan dalam penggunaan, namun method-method
yang digunakan adalah sama. Model pertama disebut GtkCombo
merupakanCombodimanauserbisamemilihataupunmenuliskan
text di dalam box entry. Yang kedua adalah GtkComboBox,
perbedaandenganmodelpertamaadalahuserhanyabisamemilih
texttanpamenuliskantext.ModelketigayaituGtkComboBoxEntry,
model ini sama halnya dengan GtkCombo. Dalam membuat objek
Combo, penulis menemukan sedikit kerancuan. Ketika membuat
objek GtkCombo akan muncul pesan warning yang menyatakan
untuk menggunakan GtkComboBoxEntry. Demi kemudahan,
penulis memutuskan hanya akan menyinggung tentang
penggunaanGtkComboBoxdenganalasanbahwapadaumumnya
data-data pada Combo bersifat fix dimana pilihan user telah
ditentukan sebelumnya. Hal ini juga demi terhindarnya kesalahan
data yang diinputkan oleh user. Method-method yang bisa
digunakandiantaranya:
append_text,mengisikandatakedalamcombo
set_active,mengaktifkandanmenampilkandatapada
comboberdasarkannilaiindek
get_active,mengembalikannilaiindekdatayangaktifatau
dipilih
get_active_text,mengembalikandatatextyangaktifatau
dipilih


89
Contoh:

#!/usr/bin/python

import gtk

class combo(gtk.Window):
def __init__(self, parent=None):
gtk.Window.__init__(self)
try:

self.set_screen(parent.get_screen())
except AttributeError:
self.connect('destroy',
lambda *w: gtk.main_quit())

self.set_title("Contoh Penggunaan
Combo")
self.set_border_width(10)
hbox1=gtk.HBox()
tabel=gtk.Table(3,1,True)
tabel.set_row_spacings(4)
tabel.set_col_spacings(4)
frame=gtk.Frame()
hbox1.pack_start(tabel,False,False,10)
hbox1.pack_start(frame,False,False,10)
self.nama1=gtk.combo_box_new_text()
isi(self.nama1, 'nama')
hbox2=gtk.HBox()
text1=gtk.Entry()
tabel.attach(hbox2, 0, 1, 0, 1)
tabel.attach(self.nama1, 0, 1, 1, 2)
tabel.attach(text1, 0, 1, 2, 3)
self.tgl1=gtk.combo_box_new_text()
isi(self.tgl1, 'tanggal')
self.bl1=gtk.combo_box_new_text()
isi(self.bl1, 'bulan')
self.th1=gtk.combo_box_new_text()
isi(self.th1, 'tahun')
hbox2.pack_start(self.tgl1,False,
False,0)
hbox2.pack_start(self.bl1,False,False,6)
hbox2.pack_start(self.th1,False,False,0)
vbox=gtk.VBox()
frame.add(vbox)
hbox3=gtk.HBox()
self.nama2=gtk.combo_box_new_text()

90
isi(self.nama2, 'nama')
self.tgl2=gtk.combo_box_new_text()
isi(self.tgl2, 'tanggal')
self.bl2=gtk.combo_box_new_text()
isi(self.bl2, 'bulan')
self.th2=gtk.combo_box_new_text()
isi(self.th2, 'tahun')
text2=gtk.Entry()
hbox3.pack_start(self.tgl2,False,
False,0)
hbox3.pack_start(self.bl2,False,False,6)
hbox3.pack_start(self.th2,False,False,0)
vbox.pack_start(self.nama2,False,
False,5)
vbox.pack_start(hbox3,False,False,5)
vbox.pack_start(text2,False,False,5)
self.nama1.set_active(1)
a=self.nama1.get_active_text()
text1.set_text(a)
self.nama2.set_active(3)
b=self.nama1.get_active()
text2.set_text(str(b))
self.add(hbox1)
self.show_all()
def isi(x=gtk.combo_box_new_text(), pilih='tanggal'):
if pilih=='nama':
n=['rido','novriana','pipit','mala',
'agung','arie']
for i in n:
x.append_text(i)
elif pilih=='tanggal':
for i in range(1,32):
x.append_text(str(i))
elif pilih=='bulan':
for i in range(1,13):
x.append_text(str(i))
else:
for i in range(1950,2501):
x.append_text(str(i))

return x

if __name__ == '__main__':
combo()
gtk.main()


91

Pada contoh di atas terdapat objek GtkTable yang memiliki


fungsi mirip dengan GtkBox yaitu dalam hal pengaturan letak
widget. Maksud dari gtk.Table(3,1,False) berarti akan dibuat
sebuah tabel dengan 3 baris 1 kolom. Parameter ketiga
berhubungan dengan ukuran area masing-masing kolom yang
dikenal dengan istilah homogeneous, jika True ukurannya akan
dibuat sama. Untuk meletakkan widget dalam tabel dilakukan
dengan format (nama widget, kiri, kanan, atas, bawah). Hitungan
posisi untuk kiri dan atas dimulai dari 0, sedangkan kanan dan
bawah dimulai dari 1. Penulis juga membuat sebuah fungsi
bernama isi() yang berfungsi untuk pengisian data ke dalam
combo.

GtkRadioButton GtkRadioButton GtkRadioButton GtkRadioButton


Widget ini umumnya bekerja secara group yang terdiri dari
beberapa pilihan, dan user hanya bisa menentukan satu pilihan.
Sebelum membuat, kita harus menentukan terlebih dahulu nama
groupnya.Biasanyanamagroupditentukanpadaobjekradiobutton
yang pertama, GTK menandai suatu radiobutton yang akan
menjadi nama group dengan None. Beberapa method yang
digunakan:
set_active,mengaktifkanpilihan
get_active,mengembalikanstatusradiobutton
set_label,menentukanlabelradiobutton
get_label,mengembalikanlabelradiobutton
set_group,menentukangroupradiobutton

92
Contoh:

#!/usr/bin/python

import gtk

class radio(gtk.Window):
def __init__(self, parent=None):
gtk.Window.__init__(self)
try:

self.set_screen(parent.get_screen())
except AttributeError:
self.connect('destroy',
lambda *w: gtk.main_quit())

self.set_title("Contoh Penggunaan
Text RadioButton")
self.set_border_width(10)
vbox=gtk.VBox()
hbox1=gtk.HBox()
hbox2=gtk.HBox()
vbox.pack_start(hbox1,False,False,3)
vbox.pack_start(hbox2,False,False,3)
pria=gtk.RadioButton(None,'Pria')
wanita=gtk.RadioButton(pria,'Wanita')
waria=gtk.RadioButton(None,'Waria')
laki=gtk.RadioButton(None,'Lelaki')
perempuan=gtk.RadioButton(laki,
'Perempuan')
banci=gtk.RadioButton(pria,'Bencong')
text1=gtk.Entry()
text2=gtk.Entry()
hbox1.pack_start(pria,False,False,3)
hbox1.pack_start(wanita,False,False,3)
hbox1.pack_start(waria,False,False,3)
hbox1.pack_start(text1,False,False,3)
hbox2.pack_start(laki,False,False,3)
hbox2.pack_start(perempuan,False,
False,3)
hbox2.pack_start(banci,False,False,3)
hbox2.pack_start(text2,False,False,3)
wanita.set_active(True)
a=wanita.get_label()
text1.set_text(a)
waria.set_group(pria)
banci.set_group(laki)

93
banci.set_active(True)
banci.set_label('Banci')
b=banci.get_active()
c=banci.get_label()
text2.set_text('Status %s pada %s'
%(b,str(c)))
self.add(vbox)
self.show_all()

if __name__ == '__main__':
radio()
gtk.main()

GtkTreeView GtkTreeView GtkTreeView GtkTreeView


GtkTreeView sebenarnya suatu objek yang ditampilkan
semacam tabel. Disini kita akan belajar memanfaatkan
GtkTreeView untuk menyajikan data dalam bentuk tabel yang
nantinya akan sangat berguna saat membuat aplikasi database.
GtkTreeView memiliki 2 model yaitu TreeStore dan ListStore,
dalam pembahasan kali ini kita akan menggunakan model
ListStore.

Contoh:

#!/usr/bin/python

import gtk

class treeview(gtk.Window):
def __init__(self, parent=None):
gtk.Window.__init__(self)
try:


94
self.set_screen(parent.get_screen())
except AttributeError:
self.connect('destroy',
lambda *w: gtk.main_quit())

self.set_title("Contoh Penggunaan
TreeView")
self.set_border_width(10)
tipekolom=gtk.ListStore(int,str,int,str)
kolom=['Nomor','Nama','Umur','Alamat']
isi=[(1,'Rido',21,'Jember'),(2,
'Novri',21,'Temanggung'),(3,'Mala',
17,'Bondowoso')]
for i in isi:
Iter=tipekolom.append()
for j in range(0,4):
tipekolom.set
(Iter,j,i[j])
tview=gtk.TreeView(tipekolom)
for x in range(0,4):
kol=gtk.TreeViewColumn
(kolom[x],gtk.
CellRendererText(),text=x)
kol.set_sort_column_id(x)
tview.append_column(kol)
tview.set_rules_hint(True)
scrol=gtk.ScrolledWindow()
scrol.set_size_request(200,100)
scrol.add(tview)
self.add(scrol)
self.show_all()

if __name__ == '__main__':
treeview()
gtk.main()


95
Pertama-tama kita membuat sebuah list yang berisi
informasitipedatadenganobjekGtkListStoredandisimpandalam
variabel bernama tipekolom. Seperti halnya tabel terdapat atribut
kolomdanbaris.Padacontohdiatasnamakolomdisimpandalam
variabel bernama kolom berbentuk list dan data setiap baris
disimpan dalam variabel bernama isi berbentuk list tuple.
Selanjutnya kita mulai memasukkan data dengan method set ke
dalam ListStore yang telah dibuat dengan metode perulangan.
Pada format method set di atas digunakan 3 parameter yaitu
prosesyangakandilakukan(methodappenduntukmenambahkan
data), nomor kolom yang dimulai dari 0, dan data masing-masing
kolom. Setelah proses tersebut selesai, baru kita membuat objek
TreeView dengan nama variabel tview yang datanya didapat dari
objekListStore.Untuknama-namakolomTreeViewmenggunakan
method append.column dengan parameter berupa objek
TreeViewColumn.Untukmembuatobjekinidigunakan3parameter
yaitu nama kolom, render text (gtk.CellRendererText), posisi
kolom. Di atas juga dicontohkan penggunaan Scroll yang
dilekatkanpadaobjekTreeView.

GtkButtondanGtkButtonBox GtkButtondanGtkButtonBox GtkButtondanGtkButtonBox GtkButtondanGtkButtonBox


GtkButtonBox merupakan box yang berfungsi dalam
pengaturan susunan widget GtkButton. Sama halnya dengan box
sebelumnya, GtkButtonBox dibagi menjadi GtkHButtonBox untuk
susunan horizontal dan GtkVButtonBox untuk susunan vertikal.
BeberapamethodGtkButtonBoxantaralain:
set_border_width,mengaturukuranborderbox
set_layout,mengaturtipeposisibutton
set_spacing,mengaturspasiantaramasing-masingbutton

Sedangkanuntukmethod-methodGtkButtonantaralain:
set_label,mengaturlabelbutton
set_use_underline,berhubungandengantombolkeyboard,
defaulnyabernilaiTrue
set_use_stock,JikabernilaiTrue,stocklabelbeserta
iconnyaakanditampilkan

96
set_image,memberigambarpadabutton

Contoh1:

#!/usr/bin/python

import gtk

class buttonbox(gtk.Window):
def __init__(self, parent=None):
gtk.Window.__init__(self)
try:

self.set_screen(parent.get_screen())
except AttributeError:
self.connect('destroy',
lambda *w: gtk.main_quit())

self.set_title("Contoh Penggunaan
ButtonBox")
self.set_border_width(10)
box=gtk.VBox()
f1=gtk.Frame('Horizontal')
f2=gtk.Frame('Vertikal')
box.pack_start(f1,False,False,3)
box.pack_start(f2,False,False,3)

vbox=gtk.VBox()
hbox=gtk.HBox()

vbox.pack_start(bbox('h',gtk.BUTTONBOX
_SPREAD,20,'Spread'),False,False,5)
vbox.pack_start(bbox('h',gtk.BUTTONBOX
_EDGE,20,'Edge'),False,False,5)
vbox.pack_start(bbox('h',gtk.BUTTONBOX
_START,20,'Start'),False,False,5)
vbox.pack_start(bbox('h',gtk.BUTTONBOX
_END,20,'End'),False,False,5)
f1.add(vbox)

hbox.pack_start(bbox('v',gtk.BUTTONBOX
_SPREAD,20,'Spread'),False,False,5)
hbox.pack_start(bbox('v',gtk.BUTTONBOX
_EDGE,20,'Edge'),False,False,5)
hbox.pack_start(bbox('v',gtk.BUTTONBOX
_START,20,'Start'),False,False,5)


97
hbox.pack_start(bbox('v',gtk.BUTTONBOX
_END,20,'End'),False,False,5)
f2.add(hbox)

self.add(box)
self.show_all()

def bbox(model='',susunan=gtk.BUTTONBOX_SPREAD,
spasi=0,title=''):
frame=gtk.Frame(title)
if model=='h':
bbox=gtk.HButtonBox()
else:
bbox=gtk.VButtonBox()
bbox.set_layout(susunan)
bbox.set_spacing(spasi)
bbox.set_border_width(3)
frame.add(bbox)

tombol=gtk.Button('Tombol1')
bbox.add(tombol)
tombol=gtk.Button('Tombol2')
bbox.add(tombol)
tombol=gtk.Button('Tombol3')
bbox.add(tombol)

return frame

if __name__ == '__main__':
buttonbox()
gtk.main()


98

Contoh2:

#!/usr/bin/python

import gtk

class button(gtk.Window):
def __init__(self, parent=None):
gtk.Window.__init__(self)
try:

self.set_screen(parent.get_screen())
except AttributeError:
self.connect('destroy',
lambda *w: gtk.main_quit())

self.set_title("Contoh Penggunaan
Button")
self.set_border_width(10)
frame=gtk.Frame()
tabel=gtk.Table(2,2,False)
tabel.set_border_width(5)

99
tabel.set_row_spacings(5)
tabel.set_col_spacings(10)
label=gtk.Label()
label.set_markup("<b>Login</b>")
label.set_alignment(0.0,0.5)
tabel.attach(label,0,1,0,1)
label=gtk.Label()
label.set_markup("<b>Password</b>")
label.set_alignment(0.0,0.5)
tabel.attach(label,0,1,1,2)
self.user=gtk.Entry()
self.passwd=gtk.Entry()
self.passwd.set_visibility(False)
tabel.attach(self.user,1,2,0,1)
tabel.attach(self.passwd,1,2,1,2)
frame.add(tabel)
bbox=gtk.HButtonBox()
bbox.set_layout(gtk.BUTTONBOX_EDGE)
bbox.set_spacing(20)
bbox.set_border_width(5)
tombol1=gtk.Button(stock='gtk-ok')
tombol1.connect('clicked',self.cetak)
bbox.add(tombol1)
tombol2=gtk.Button('_Quit')
gambar=gtk.Image()
gambar.set_from_file
('gambar/keluar.png')
tombol2.set_image(gambar)
tombol2.connect('clicked',
lambda *w: gtk.main_quit())
bbox.add(tombol2)
vbox=gtk.VBox()
vbox.pack_start(frame,False,False,5)
vbox.pack_start(bbox,False,False,5)
self.add(vbox)
self.show_all()
def cetak(self,x):
print 'User anda:', self.user.get_text()
print 'Password anda:',
self.passwd.get_text()
self.user.set_text('')
self.passwd.set_text('')
self.set_focus(self.user)

if __name__ == '__main__':
button()
gtk.main()


100



GtkMessageDialog GtkMessageDialog GtkMessageDialog GtkMessageDialog
PyGTKmenyediakan4jenisdialogpesanyaitu:
gtk.MESSAGE_lNFO,pesanberupainformasi
gtk.MESSAGE_WARNlNG,pesanberupaperingatan
gtk.MESSAGE_QUESTlON,pesanberupapertanyaan
gtk.ERROR,pesanuntukmenampilkankesalahan

Sedangkanuntuktombolyangditampilkanada5jenis:
gtk.BUTTONS_OK,menampilkantombolOK
gtk.BUTTONS_CANCEL,menampilkantombolCancel
gtk.BUTTONS_OK_CANCEL,menampilkantombolOK
danCancel
gtk.BUTTONS_YES_NO,menampilkantombolYesdan
No
gtk.BUTTONS_CLOSE,menampilkantombolClose

Contoh:

#!/usr/bin/python

import gtk

class dialog(gtk.Window):
def __init__(self, parent=None):
gtk.Window.__init__(self)
try:

self.set_screen(parent.get_screen())
except AttributeError:
self.connect('destroy',
lambda *w: gtk.main_quit())

101
self.set_title("Contoh Penggunaan
Message Dialog")
self.set_border_width(10)
box=gtk.HButtonBox()
tombol1=gtk.Button('Dialog 1')
tombol1.connect('clicked',self.klik,1)
box.add(tombol1)
tombol2=gtk.Button('Dialog 2')
tombol2.connect('clicked',self.klik,2)
box.add(tombol2)
tombol3=gtk.Button('Dialog 3')
tombol3.connect('clicked',self.klik,3)
box.add(tombol3)
tombol4=gtk.Button('Dialog 4')
tombol4.connect('clicked',self.klik,4)
box.add(tombol4)
tombol5=gtk.Button('Dialog 5')
tombol5.connect('clicked',self.klik,5)
box.add(tombol5)
self.add(box)
self.show_all()

def klik(self,tombol,y=1):
if y==1:
pesan(self,gtk.MESSAGE_INFO,
gtk.BUTTONS_OK,'Ini adalah
Dialog Info')
elif y==2:
pesan(self,gtk.MESSAGE_
WARNING,gtk.BUTTONS_CANCEL,
'Ini adalah Dialog Warning')
elif y==3:
pesan(self,gtk.MESSAGE_
QUESTION,gtk.BUTTONS_OK_
CANCEL,'Ini adalah Dialog
Question')
elif y==4:
pesan(self,gtk.MESSAGE_
QUESTION,gtk.BUTTONS_YES_NO,
'Ini adalah Dialog Question')
else:
pesan(self,gtk.MESSAGE_
ERROR,gtk.BUTTONS_CLOSE,'Ini
adalah Dialog Error')


def pesan(a=None,b=None,c=gtk.BUTTONS_OK,text=''):
message=gtk.MessageDialog(a, gtk.DIALOG_MODAL

102
| gtk.DIALOG_DESTROY_WITH_PARENT,
b, c, text)
respon=message.run()
if respon==gtk.RESPONSE_OK:
print 'Tombol OK'
elif respon==gtk.RESPONSE_CANCEL:
print 'Tombol Cancel'
elif respon==gtk.RESPONSE_YES:
print 'Tombol Yes'
elif respon==gtk.RESPONSE_NO:
print 'Tombol No'
elif respon==gtk.RESPONSE_CLOSE:
print 'Tombol Close'
message.destroy()

if __name__ == '__main__':
dialog()
gtk.main()


103
Untuk mengetahui tombol apa yang diklik bisa
menggunakan gtk.RESPONSE_<nama tombol>. Gtk.RESPONSE
akan berguna untuk menentukan langkah berikutnya dari tombol
yangdiklik.

MenudanToolbar MenudanToolbar MenudanToolbar MenudanToolbar


Untuk membuat menu bisa menggunakan 2 alternatif yaitu
menggunakan widget GtkMenuBar atau GtkUlManager, dalam
pembahasan ini penulis menjatuhkan pilihan pada GtkUlManager.
DenganGtkUlManagerkitabisamembuatkreasimenudantoolbar
secara bersamaan. Sedangkan pada GtkMenuBar hanya untuk
membuat objek menu saja, objek tollbar terpisah yaitu
menggunakan widget GtkToolbar. Dalam membuat menu dengan
GtkUlManager, terlebih dahulu kita harus menentukan informasi
variabel-variabel menu dan item toolbar beserta susunannya
dengan cara mirip menuliskan kode html, baru kemudian
menentukanhal-hallainsepertiisimenu,method,dsb.

Contoh:

#!/usr/bin/python

import gtk

info = \
'''<ui>
<menubar name='MenuBar'>
<menu action='FileMenu'>
<menuitem action='New'/>
<menuitem action='Open'/>
<menuitem action='Save'/>
<separator/>
<menuitem action='Quit'/>
</menu>
<menu action='EditMenu'>
<menuitem action='Copy'/>
<menuitem action='Paste'/>
</menu>
<menu action='HelpMenu'>
<menuitem action='About'/>
</menu>

104
</menubar>
<toolbar name='ToolBar'>
<toolitem action='New'/>
<toolitem action='Open'/>
<separator/>
<toolitem action='Save'/>
</toolbar>
</ui>'''

class MainMenu(gtk.Window):
def __init__(self, parent=True):
gtk.Window.__init__(self)
try:

self.set_screen(parent.get_screen())
except AttributeError:
self.connect('destroy',
lambda *w: gtk.main_quit())

self.set_title("Contoh Penggunaan
UIManager")
self.set_border_width(5)
self.set_default_size(300, 300)
self.set_resizable(True)

merge = gtk.UIManager()
self.set_data("ui-manager", merge)
merge.insert_action_group(self.ui(), 0)
self.add_accel_group(merge.get_accel
_group())

try:
mergeid = merge.add_ui_from_
string(info)
except gobject.GError, msg:
print "Kesalahan saat membuat
Menu: %s" % msg
bar = merge.get_widget("/MenuBar")
bar.show()

tabel = gtk.Table(1, 4, False)
self.add(tabel)
tabel.attach(bar,0,1,0,1,gtk.EXPAND
| gtk.FILL,0,0,0);
bar = merge.get_widget("/ToolBar")
bar.set_tooltips(True)
bar.show()


105
tabel.attach(bar,0,1,1,2,gtk.EXPAND
|gtk.FILL,0,0,0);
konten = gtk.TextView()
konten.grab_focus()
konten.set_sensitive(False)
sw = gtk.ScrolledWindow()
sw.set_policy(gtk.POLICY_AUTOMATIC,
gtk.POLICY_AUTOMATIC)
sw.set_shadow_type(gtk.SHADOW_IN)
sw.add (konten)
tabel.attach(sw,0,1,2,3,gtk.EXPAND
| gtk.FILL, gtk.EXPAND |
gtk.FILL,0,0)
self.statusbar = gtk.Statusbar()
tabel.attach(self.statusbar,0,1,3,4,
gtk.EXPAND | gtk.FILL,0,0,0)
self.update_statusbar()
self.connect("window_state_event",
self.update_resize_grip)
self.set_position(gtk.WIN_POS_CENTER)
self.show_all()

def ui(self):
entry=(("FileMenu",None,"_File"),
("EditMenu",None,"_Edit"),("HelpMenu"
,None,"_Help"),
("New",None,"_New","<control>N",
"Dialog 1",self.masuk),
("Open",None,"_Open","<control>O",
"Dialog 2",self.masuk),
("Save",None,"_Save","<control>S",
"Dialog 3",self.masuk),
("Quit",None,"_Quit","<control>Q",
"Keluar",self.masuk),
("Copy",None,"_Copy","<control>C",
"Dialog 4",self.masuk),
("Paste",None,"_Paste","<control>V",
"Dialog 5",self.masuk),
("About",None,"_About",None,
"Dialog 6",self.masuk));

# Membuat menubar dan toolbar
isi_group = gtk.ActionGroup
("AppWindowActions")
isi_group.add_actions(entry)

return isi_group


106
def masuk(self, action):
if action.get_name()=='New':
pesan(self,gtk.MESSAGE_INFO,
gtk.BUTTONS_OK,'Anda memilih
menu New')
if action.get_name()=='Open':
pesan(self,gtk.MESSAGE_INFO,
gtk.BUTTONS_OK,'Anda memilih
menu Open')
if action.get_name()=='Save':
pesan(self,gtk.MESSAGE_INFO,
gtk.BUTTONS_OK,'Anda memilih
menu Save')
if action.get_name()=='Quit':
gtk.main_quit()
if action.get_name()=='Copy':
pesan(self,gtk.MESSAGE_INFO,
gtk.BUTTONS_OK,'Anda memilih
menu Copy')
if action.get_name()=='Paste':
pesan(self,gtk.MESSAGE_INFO,
gtk.BUTTONS_OK,'Anda memilih
menu Paste')
if action.get_name()=='About':
pesan(self,gtk.MESSAGE_INFO,
gtk.BUTTONS_OK,'Anda memilih
menu About')

def update_statusbar(self):
self.statusbar.pop(0)
self.statusbar.push(0,"Contoh
Aplikasi Menggunakan UIManager")

def update_resize_grip(self, widget, event):
mask = gtk.gdk.WINDOW_STATE_MAXIMIZED
| gtk.gdk.WINDOW_STATE_FULLSCREEN
if (event.changed_mask & mask):
self.statusbar.set_has_resize
_grip(not (event.new_window_
state & mask))

def pesan(a=None,b=None,c=gtk.BUTTONS_OK,text=''):
message=gtk.MessageDialog(a, gtk.DIALOG_MODAL
| gtk.DIALOG_DESTROY_WITH_PARENT,
b, c, text)
message.run()
message.destroy()


107
if __name__ == '__main__':
MainMenu()
gtk.main()

Dari contoh di atas objek GtkUlManager disimpan dalam


variabel bernama merge, selanjutnya informasi susunan ui
dipanggil dengan method add_ui_from_string. Berdasarkan
informasi ini baru dibuat widget menu dan toolbar yang disimpan
dalam variabel bernama bar. Perhatikan fungsi ui, disini kita
membuat objek tuple yang berisi penjabaran item-item menu
secararinci.lsitupletersebutdapatdijelaskansebagaiberikut:
formatpengisiandimulaidengannamamenuterlebih
dahulukemudiannamaitemmenu
untukformatparametermenu(nama,stockgambar,label)
untuk format parameter item menu (nama, stock gambar,
label,kombinasitombol,keterangan,method)

SelainUlManager,dicontohkanpulapenggunaanTextView,
ScrolledWindow, dan StatusBar. Widget-widget ini dibuat hanya
untuksebuahmanipulasiagartampilanmenulebihmenarik.


108
Demikian sedikit pengenalan PyGTK yang penulis rasa
masih sangat jauh dari sempurna terutama widget-widget yang
dipaparkan hanya beberapa saja dari sekian banyak stok widget
GTK. Alasan dari semua ini sebagai pembatasan masalah yang
penulis paparkan. lnsyaAllah bila diberi kemampuan penulis akan
mencoba merealisasikan buku yang memaparkan tentang
penggunaanPyGTKsecarakhusus,mohondoanyaya...
Untuk bagian selanjutnya penulis akan mencontohkan
sebuah simulasi aplikasi database yang akan menggunakan
semua module yang telah dijelaskan yaitu XMLRPC, pg, socket,
time, dan GTK. Sehingga akan lebih terasa kebenaran dari judul
bukuini,PYTHON++.


109
Judul Judul Judul Judul : :: : Membuat Membuat Membuat MembuatAplikasi++ Aplikasi++ Aplikasi++ Aplikasi++
Keterangan Keterangan Keterangan Keterangan : :: : SimulasiAplikasiDatabase SimulasiAplikasiDatabase SimulasiAplikasiDatabase SimulasiAplikasiDatabase
menggunakanmoduleXMLRPC, menggunakanmoduleXMLRPC, menggunakanmoduleXMLRPC, menggunakanmoduleXMLRPC,
pg,socket,dll pg,socket,dll pg,socket,dll pg,socket,dll

Metodepengerjaan:
Aplikasimenggunakanmetodedistributedprogramming
AplikasiclientberhubungandenganGUl
Aplikasiserverberhubungandengankoneksidatabase
server

Resourceyangdibutuhkan:
Alokasiminimumcukupdengan1komputerdengansistem
operasiLinux
Disarankanmenggunakan2ataulebihkomputer

Prosespengerjaan:
Membuat database dan tabel baru dengan nama masing-
masing tuxhouse dan profile pada komputer tempat
aplikasiserverdiletakkan:

# su rido
$ createdb tuxhouse
$ psql -d tuxhouse
Welcome to psql 8.0.3, the PostgreSQL interactive
terminal.

Type: \copyright for distribution terms
\h for help with SQL commands
\? for help with psql commands
\g or terminate with semicolon to execute query
\q to quit

tuxhouse=> alter user rido with encrypter password
'rahasia';
tuxhouse=> create table profile(
tuxhouse(> nim char(10) not null,
tuxhouse(> nama varchar(40) not null,
tuxhouse(> alamat varchar(50),
tuxhouse(> tmplahir varchar(20),

110
tuxhouse(> tgllahir date,
tuxhouse(> jk boolean,
tuxhouse(> agama char(2),
tuxhouse(> CONSTRAINT profile_pk PRIMARY KEY(nim));

Penerapan keamanan database server dengan kriteria


hanya menerima koneksi secara lokal dan menggunakan
metode md5 sebagai user enkripsinya. File yang
berhubungan dengan keamanan database PostgreSQL
adalah pg_hba.conf yang terletak di dalam direktori data
server database yang pernah dibuat sebelumnya yaitu
/usr/local/pgsql/data. lnformasi yang perlu ditambahkan
adalahpadabagian"local:

# "local" is for Unix domain socket connections only


local tuxhouse rido md5

Membuat aplikasi client berupa GUl yang terdiri dari


tampilan Login, Menu Utama, Profile, Laporan, dan About
Program yang diletakkan dan dijalankan pada sisi client,
berikutskripnya:

#!/usr/bin/env python

import gtk
import xmlrpclib
import webbrowser
import gobject
import md5

kirim=xmlrpclib.Server('http://172.16.0.2:2006')

ui_info = \
'''<ui>
<menubar name='MenuBar'>
<menu action='FileMenu'>
<menuitem action='Profile'/>
<separator/>
<menuitem action='Keluar'/>
</menu>
<menu action='LaporanMenu'>
<menuitem action='LapProfile'/>
</menu>
<menu action='HelpMenu'>

111
<menuitem action='About'/>
</menu>
</menubar>
<toolbar name='ToolBar'>
<toolitem action='Profile'/>
<separator/>
<toolitem action='LapProfile'/>
</toolbar>
</ui>'''

class Login(gtk.Window):
def __init__(self, parent=True):
gtk.Window.__init__(self)
try:

self.set_screen(parent.get_screen())
except AttributeError:
self.connect('destroy',
lambda *w: gtk.main_quit())

self.set_title("Login")
self.set_border_width(10)
self.set_default_size(320, 100)
self.set_resizable(True)

vbox = gtk.VBox(False,5)
frame = gtk.Frame()
tabel = gtk.Table(2,2,False)
tabel.set_border_width(10)
tabel.set_row_spacings(10)
tabel.set_col_spacings(15)
label = gtk.Label()
label.set_alignment(0,0.5)
label.set_markup("<b>Login</b>")
tabel.attach(label, 0, 1, 0, 1)
label = gtk.Label()
label.set_alignment(0,0.5)
label.set_markup("<b>Password</b>")
tabel.attach(label, 0, 1, 1, 2)
self.user = gtk.Entry()
self.passwd = gtk.Entry()
self.passwd.set_visibility(False)
self.passwd.set_invisible_char('*')
tabel.attach(self.user, 1, 2, 0, 1)
tabel.attach(self.passwd, 1, 2, 1, 2)
frame.add(tabel)
hbox = gtk.HBox(False, 20)


112
tombol = gtk.Button('_OK')
image = gtk.Image()
image.set_from_file('icon/ok.png')
tombol.set_image(image)
tombol.connect('clicked', self.ok)
hbox.pack_start(tombol)

tombol = gtk.Button('_Batal')
image = gtk.Image()
image.set_from_file('icon/batal.png')
tombol.set_image(image)
tombol.connect('clicked', gtk.main_quit)
hbox.pack_start(tombol)

vbox.pack_start(frame,False,False,5)
vbox.pack_start(hbox,False,False,5)

self.add(vbox)
self.set_position(gtk.WIN_POS_CENTER)
self.show_all()

def ok(self, tombol):
if self.user.get_text()=='':
pesan(self,gtk.MESSAGE_
WARNING,"Isikan dahulu data
pada kolom user!")
self.set_focus(self.user)
elif self.passwd.get_text()=='':
pesan(self,gtk.MESSAGE_
WARNING,"Isikan dahulu data
pada kolom password!")
self.set_focus(self.passwd)
else:
try:
kembali = kirim.login
([self.user.get_text()
,md5.new(self.passwd.
get_text()).hexdigest()])
except:
kembali = 3
if kembali==1:
pesan(self,gtk.
MESSAGE_ERROR,"Koneksi
ke Database Server
gagal.")
self.user.set_text('')
self.passwd.set_text('')


113
self.set_focus
(self.user)
elif kembali==2:
self.hide()
MainMenu()
else:
pesan(self,gtk.
MESSAGE_ERROR,"Koneksi
XMLRPC gagal.")

class MainMenu(gtk.Window):
def __init__(self, parent=True):
register_stock_icons()
gtk.Window.__init__(self)
try:

self.set_screen(parent.get_screen())
except AttributeError:
self.connect('destroy',
lambda *w: gtk.main_quit())

self.set_title("Menu Utama")
self.set_border_width(5)
self.set_default_size(800, 600)
self.set_resizable(True)

merge = gtk.UIManager()
self.set_data("ui-manager", merge)
merge.insert_action_group(self.ui(), 0)
self.add_accel_group(merge.get_accel
_group())

try:
mergeid = merge.add_ui_from_
string(ui_info)
except gobject.GError, msg:
print "building menus failed:
%s" % msg
bar = merge.get_widget("/MenuBar")
bar.show()

tabel = gtk.Table(1, 4, False)
self.add(tabel)
tabel.attach(bar,0,1,0,1,gtk.EXPAND
| gtk.FILL,0,0,0);
bar = merge.get_widget("/ToolBar")
bar.set_tooltips(True)
bar.show()

114
tabel.attach(bar,0,1,1,2,gtk.EXPAND
| gtk.FILL,0,0,0);
contents = gtk.TextView()
contents.grab_focus()
contents.set_sensitive(False)
sw = gtk.ScrolledWindow()
sw.set_policy(gtk.POLICY_AUTOMATIC,
gtk.POLICY_AUTOMATIC)
sw.set_shadow_type(gtk.SHADOW_IN)
sw.add (contents)
tabel.attach(sw,0,1,2,3,gtk.EXPAND
| gtk.FILL, gtk.EXPAND |
gtk.FILL,0,0)
self.statusbar = gtk.Statusbar()
tabel.attach(self.statusbar,0,1,3,4,
gtk.EXPAND | gtk.FILL,0,0,0)
self.update_statusbar()
self.connect("window_state_event",
self.update_resize_grip)
self.set_position(gtk.WIN_POS_CENTER)
self.show_all()

def ui(self):
entry=(("FileMenu",None,"_Aplikasi"),
("LaporanMenu",None,"_Laporan"),
("HelpMenu",None,"_Bantuan"),
("Profile","profile","_Profile",
"<control>P","Profile Diri",
self.masuk),
("Keluar","keluar","_Keluar",
"<control>K","Keluar",self.masuk),
("LapProfile","laporan","Laporan Data
Profile",None,"Laporan Profile",
self.masuk),
("About","about","About Program",
None,"About Program",self.masuk));

# Create the menubar and toolbar
isi_group = gtk.ActionGroup
("AppWindowActions")
isi_group.add_actions(entry)

return isi_group

def masuk(self, action):
if action.get_name()=='Keluar':
gtk.main_quit()
if action.get_name()=='Profile':

115
Profile()
if action.get_name()=='LapProfile':
viewlaporan().lihat('profile',7)
if action.get_name()=='About':
About()

def update_statusbar(self):
self.statusbar.pop(0)
self.statusbar.push(0,"APLIKASI++")

def update_resize_grip(self, widget, event):
mask = gtk.gdk.WINDOW_STATE_MAXIMIZED
| gtk.gdk.WINDOW_STATE_FULLSCREEN
if (event.changed_mask & mask):
self.statusbar.set_has_resize
_grip(not (event.new_window_
state & mask))

class About(gtk.Window):
def __init__(self, parent=None):
gtk.Window.__init__(self)
try:

self.set_screen(parent.get_screen())
except AttributeError:
self.connect('destroy',
lambda *w: self.destroy())

self.set_title("About Aplikasi++")
self.set_border_width(10)
self.set_resizable(False)

vbox=gtk.VBox()
hbox=gtk.HBox()
frame=gtk.Frame()
image = gtk.Image()
image.set_from_file('icon/program.png')
frame.add(image)
box=gtk.VBox()
label=gtk.Label('Title : Aplikasi++')
label.set_alignment(0.0,0.5)
box.pack_start(label,False,False,5)
label=gtk.Label('Author : Mahdi Ridho')
label.set_alignment(0.0,0.5)
box.pack_start(label,False,False,5)
label=gtk.Label('Versi : 1.0')
label.set_alignment(0.0,0.5)
box.pack_start(label,False,False,5)

116
label=gtk.Label('Date : Saturday 4
November 2006')
label.set_alignment(0.0,0.5)
box.pack_start(label,False,False,5)
hbox.pack_start(frame,False,False,10)
hbox.pack_start(box,False,False,10)
tombol = gtk.Button('_OK')
image = gtk.Image()
image.set_from_file('icon/ok.png')
tombol.set_image(image)
tombol.connect('clicked',
lambda *w: self.destroy())
vbox.pack_start(hbox,False,False,10)
vbox.pack_start(tombol,False,False,10)

self.add(vbox)
self.set_position(gtk.WIN_POS_CENTER)
self.show_all()

class Profile(gtk.Window):
def __init__(self, parent=None):
gtk.Window.__init__(self)
try:
self.set_screen(parent.get_
screen())
except AttributeError:
self.connect('destroy',
lambda *w: self.destroy())

self.set_title("Administrasi Profile")
self.set_border_width(10)
self.set_resizable(False)

vbox = gtk.VBox()
self.add(vbox)

frame = gtk.Frame()
hbawah = gtk.HButtonBox()
vbox.pack_start(frame, padding=3)
vbox.pack_start(hbawah, False, False, 5)

vbox2 = gtk.VBox()
frame.add(vbox2)

label = gtk.Label()
label.set_markup("<b>ADMINISTRASI
DATA PROFILE</b>")
label.set_alignment(0.5, 0.5)

117
hbox = gtk.HBox(False, 20)
hbox.set_border_width(5)
vbox2.pack_start(label,False,False,15)
vbox2.pack_start(gtk.HSeparator(),
False,False,0)
vbox2.pack_start(hbox,False,False,5)

tabel = gtk.Table(6,2,False)
tabel.set_row_spacings(4)
tabel.set_col_spacings(20)
hbox.pack_start(tabel,False,False,0)
hbox.pack_start(self.TombolBox(True,
2,gtk.BUTTONBOX_START),False,False,0)

label = gtk.Label("N I M")
label.set_alignment(0, 0.5)
tabel.attach(label, 0, 1, 0, 1)
label = gtk.Label("Nama")
label.set_alignment(0, 0.5)
tabel.attach(label, 0, 1, 1, 2)
label = gtk.Label("Alamat")
label.set_alignment(0, 0.5)
tabel.attach(label, 0, 1, 2, 3)
label = gtk.Label("Kelahiran")
label.set_alignment(0, 0.5)
tabel.attach(label, 0, 1, 3, 4)
label = gtk.Label("Jenis Kelamin")
label.set_alignment(0, 0.5)
tabel.attach(label, 0, 1, 4, 5)
label = gtk.Label("Agama")
label.set_alignment(0, 0.5)
tabel.attach(label, 0, 1, 5, 6)

self.nim = gtk.Entry()
self.nim.set_max_length(10)
self.carinim = gtk.Entry()
self.carinim.set_sensitive(False)
self.nama = gtk.Entry()
self.alamat = gtk.Entry()
self.tmplahir = gtk.Entry()
self.tgllahir = gtk.combo_box_new_text()
kalender(self.tgllahir, 'tanggal')
self.bllahir = gtk.combo_box_new_text()
kalender(self.bllahir, 'bulan')
self.thlahir = gtk.combo_box_new_text()
kalender(self.thlahir, 'tahun')
self.pria = gtk.RadioButton(None,'Pria')


118
self.wanita = gtk.RadioButton
(self.pria,'Wanita')
self.agama = gtk.combo_box_new_text()

hnim = gtk.HBox(True,0)
hnim.pack_start(self.nim,False,False, 0)
hnim.pack_start(self.carinim,False,
False, 0)

hlahir = gtk.HBox(False,0)
tabel1 = gtk.Table(1,2,False)
tabel1.set_col_spacings(4)
tabel1.attach(self.tmplahir, 0, 1, 0, 1)
tabel1.attach(hlahir, 1, 2, 0, 1)
hlahir.pack_start(self.tgllahir,False,
False,0)
hlahir.pack_start(self.bllahir,False,
False,0)
hlahir.pack_start(self.thlahir,False,
False,0)

hjk = gtk.HBox(False,115)
hjk.pack_start(self.pria,False,False,0)
hjk.pack_start(self.wanita,False,
False,0)

self.agama.append_text('Islam')
self.agama.append_text('Katolik')
self.agama.append_text('Protestan')
self.agama.append_text('Hindu')
self.agama.append_text('Buddha')
self.agama.append_text('Kepercayaan')
self.agama.append_text('Lain - Lain')

tabel.attach(hnim, 1, 2, 0, 1)
tabel.attach(self.nama, 1, 2, 1, 2)
tabel.attach(self.alamat, 1, 2, 2, 3)
tabel.attach(tabel1, 1, 2, 3, 4)
tabel.attach(hjk, 1, 2, 4, 5)
tabel.attach(self.agama, 1, 2, 5, 6)

hbawah.set_layout(gtk.BUTTONBOX_END)
hbawah.set_spacing(30)
tombol = gtk.Button('_Laporan')
image = gtk.Image()
image.set_from_file('icon/laporan.png')
tombol.set_image(image)
tombol.connect('clicked', self.laporan)

119
hbawah.add(tombol)
tombol = gtk.Button('_Batal')
image = gtk.Image()
image.set_from_file('icon/batal.png')
tombol.set_image(image)
tombol.connect('clicked', self.batal)
hbawah.add(tombol)
tombol = gtk.Button('_Keluar')
image = gtk.Image()
image.set_from_file('icon/keluar.png')
tombol.set_image(image)
tombol.connect('clicked', self.keluar)
hbawah.add(tombol)

self.set_position(gtk.WIN_POS_CENTER)
self.show_all()
self.fresh()

def TombolBox(self, vertikal=True, spasi = 0,
susunan = gtk.BUTTONBOX_SPREAD):
if vertikal:
tbox = gtk.VButtonBox()
else:
tbox = gtk.HButtonBox()

tbox.set_border_width(0)
tbox.set_layout(susunan)
tbox.set_spacing(spasi)

tombol = gtk.Button('_Cari')
image = gtk.Image()
image.set_from_file('icon/cari.png')
tombol.set_image(image)
tombol.connect('clicked', self.cari)
tbox.add(tombol)

tombol = gtk.Button('_Simpan')
image = gtk.Image()
image.set_from_file('icon/simpan.png')
tombol.set_image(image)
tombol.connect('clicked', self.simpan)
tbox.add(tombol)

self.tombol1 = gtk.Button('_Ubah')
image = gtk.Image()
image.set_from_file('icon/ubah.png')
self.tombol1.set_image(image)


120
self.tombol1.connect('clicked',
self.ubah)
tbox.add(self.tombol1)

self.tombol2 = gtk.Button('_Hapus')
image = gtk.Image()
image.set_from_file('icon/hapus.png')
self.tombol2.set_image(image)
self.tombol2.connect('clicked',
self.hapus)
tbox.add(self.tombol2)

return tbox

def simpan(self, tombol):
if self.nim.get_text()=='':
pesan(self,gtk.MESSAGE_
WARNING,"Tolong isikan NIM
anda!")
self.set_focus(self.nim)
elif self.nama.get_text()=='':
pesan(self,gtk.MESSAGE_
WARNING,"Tolong isikan Nama
anda!")
self.set_focus(self.nama)
elif self.tmplahir.get_text()=='' or
self.tgllahir.get_active_text()==
None or self.bllahir.get_active_
text()==None or self.thlahir.get_
active_text()==None:
pesan(self,gtk.MESSAGE_
WARNING,"Tolong isikan Tempat
dan Tanggal Lahir anda!")
self.set_focus(self.tmplahir)
else:
try:
kembali=kirim.simpan
(['profile',self.nim.
get_text(),'nim',
(self.nim.get_text(),
self.nama.get_text(),
self.alamat.get_text()
,self.tmplahir.get_
text(),self.tgllahir.
get_active_text(),self
.bllahir.get_active_
text(),self.thlahir.
get_active_text(),self

121
.pria.get_active(),
self.agama.get_active())])
except:
kembali = 4
if kembali==1:
pesan(self,gtk.
MESSAGE_ERROR,"Koneksi
ke Database Server
gagal.")
self.fresh()
elif kembali==2:
pesan(self,gtk.
MESSAGE_INFO,"Data
dengan NIM %s sudah
ada."%(self.nim.get_
text()))
self.nim.set_text('')
self.set_focus(self.nim)
elif kembali==3:
pesan(self,gtk.
MESSAGE_INFO,"Data
berhasil disimpan")
self.fresh()
else:
pesan(self,gtk.
MESSAGE_ERROR,"Koneksi
XMLRPC gagal.")
self.fresh()

def cari(self, tombol):
if self.nim.get_text()=='':
pesan(self,gtk.
MESSAGE_WARNING,"Tolong
isikan NIM yang dicari!")
self.set_focus(self.nim)
else:
try:
kembali=kirim.cari
(['profile',self.nim.
get_text(),'nim'])
except:
kembali = [4]
if kembali[0]==1:
pesan(self,gtk.
MESSAGE_ERROR,"Koneksi
ke Database Server
gagal.")
self.fresh()

122
elif kembali[0]==2:
pesan(self,gtk.
MESSAGE_INFO,"Data
dengan NIM %s tidak
ada."%(self.nim.get_
text()))
self.fresh()
elif kembali[0]==3:
self.tombol1.set_
sensitive(True)
self.tombol2.set_
sensitive(True)
self.carinim.set_
text(kembali[1])
self.nama.set_
text(kembali[2])
self.alamat.set_
text(kembali[3])
self.tmplahir.set_
text(kembali[4])
k=kembali[5] t=k[8:10]
;b=k[5:7];h=k[0:4]
pecah(t,b,h,self.
tgllahir,self.bllahir,
self.thlahir)
if kembali[6]=='t':
self.pria.set
_active(1)
else:
self.wanita.
set_active(1)
self.agama.set_active
(int(kembali[7]))
else:
pesan(self,gtk.
MESSAGE_ERROR,"Koneksi
XMLRPC gagal.")
self.fresh()

def ubah(self, tombol1):
if self.nim.get_text()=='':
pesan(self,gtk.MESSAGE_
WARNING,"Tolong isikan NIM
anda!")
self.set_focus(self.nim)
elif self.nama.get_text()=='':
pesan(self,gtk.MESSAGE_
WARNING,"Tolong isikan Nama

123
anda!")
self.set_focus(self.nama)
elif self.tmplahir.get_text()=='' or
self.tgllahir.get_active_text()==None
or self.bllahir.get_active_text()==
None or self.thlahir.get_active_
text()==None:
pesan(self,gtk.MESSAGE_
WARNING,"Tolong isikan Tempat
dan Tanggal Lahir anda!")
self.set_focus(self.tmplahir)
else:
try:
kembali=kirim.ubah
(['profile',self.nim.
get_text(),'nim',(self
.nim.get_text(),self.
nama.get_text(),self.
alamat.get_text(),self
.tmplahir.get_text(),
self.tgllahir.get_
active_text(),self.
bllahir.get_active_
text(),self.thlahir.
get_active_text(),
self.pria.get_active()
,self.agama.get_
active(),self.carinim
.get_text())])
except:
kembali = 4
if kembali==1:
pesan(self,gtk.
MESSAGE_ERROR,"Koneksi
ke Database Server
gagal.")
self.fresh()
elif kembali==2:
pesan(self,gtk.
MESSAGE_INFO,"Data
dengan NIM %s sudah
ada."%(self.nim.get_
text()))
self.nim.set_text('')
self.set_focus(self.nim)
elif kembali==3:
pesan(self,gtk.
MESSAGE_INFO,"Data

124
berhasil diubah")
self.fresh()
else:
pesan(self,gtk.
MESSAGE_ERROR,"Koneksi
XMLRPC gagal.")
self.fresh()

def hapus(self, tombol2):
dialog = gtk.MessageDialog(self,
gtk.DIALOG_MODAL |
gtk.DIALOG_DESTROY_WITH_PARENT,
gtk.MESSAGE_QUESTION,gtk.BUTTONS_YES
_NO, "Apakah anda yakin ingin
menghapus data?")
respon=dialog.run()
if respon == gtk.RESPONSE_NO:
self.fresh()
else:
try:
kembali=kirim.hapus
(self.carinim.get_text())
except:
kembali = 3
if kembali==1:
pesan(self,gtk.
MESSAGE_ERROR,"Koneksi
ke Database Server
gagal.")
self.fresh()
elif kembali==2:
pesan(self,gtk.
MESSAGE_INFO,"Data
berhasil dihapus")
self.fresh()
else:
pesan(self,gtk.
MESSAGE_ERROR,"Koneksi
XMLRPC gagal.")
self.fresh()
dialog.destroy()

def batal(self, tombol):
self.fresh()

def laporan(self, tombol):
viewlaporan().lihat('profile',7)


125
def keluar(self, tombol):
self.destroy()

def fresh(self):
self.nim.set_text('')
self.carinim.set_text('')
self.nama.set_text('')
self.alamat.set_text('')
self.tmplahir.set_text('')
self.tgllahir.set_active(-1)
self.bllahir.set_active(-1)
self.thlahir.set_active(-1)
self.pria.set_active(1)
self.agama.set_active(-1)
self.set_focus(self.nim)
self.tombol1.set_sensitive(False)
self.tombol2.set_sensitive(False)

def pecah(self, a='', b='', c ='', d=gtk.
combo_box_new_text,e=gtk.combo_box_new_text,
f=gtk.combo_box_new_text):
i=0
d.set_active(i)
e.set_active(i)
f.set_active(i)
if a[0:1]=='0':
a=a[1:2]
if b[0:1]=='0':
b=b[1:2]
for i in range(0,31):
if a==d.get_active_text():
i=31
else:
d.set_active(i)
for i in range(0,12):
if b==e.get_active_text():
i=12
else:
e.set_active(i)
for i in range(0,1450):
if c==f.get_active_text():
i=1450
else:
f.set_active(i)

class viewlaporan(gtk.Window):
def __init__(self, parent=None):
gtk.Window.__init__(self)

126
try:
self.set_screen(parent.get_
screen())
except AttributeError:
self.connect('destroy',
lambda *w: self.hide())

self.set_title("Laporan Data Profile")
self.set_border_width(10)
self.set_resizable(True)

def lihat(self, jenis='',jml=0):
try:
self.data=kirim.lapor(jenis,jml)
except:
self.data = 2
if self.data==1:
pesan(self,gtk.MESSAGE_ERROR,
"Koneksi ke Database Server
gagal.")
elif self.data==2:
pesan(self,gtk.MESSAGE_ERROR,
"Koneksi XMLRPC gagal.")
else:
frame=gtk.Frame()
vbox=gtk.VBox()
frame.add(vbox)
isidata=gtk.ListStore(str,str
,str,str,str,str,str)
self.label=gtk.Label()
self.label.set_markup("<b>
LAPORAN PROFILE</b>")
self.label.set_alignment
(0.5,0.5)
hbox=gtk.HBox()
vbox.pack_start(self.label,
False,False,5)
vbox.pack_start(hbox,
False,False,0)

frame1=gtk.Frame()
frame1.set_border_width(30)
self.satu = gtk.RadioButton
(None,'NIM')
self.satu.connect("clicked",
self.radio1)
self.semua = gtk.RadioButton
(self.satu,'Semua Profile')

127
self.semua.connect("clicked",
self.radio2)
vbox1=gtk.VBox()
vbox1.pack_start(self.satu,
False,False,5)
vbox1.pack_start(self.semua,
False,False,5)
frame1.add(vbox1)
hbox.pack_start(frame1,
False,False,40)

self.hbox1=gtk.HBox()
self.label=gtk.Label("NIM")
self.label.set_alignment
(0.5,0.5)
self.n=gtk.Entry()
self.n.set_max_length(10)
self.hbox1.pack_start
(self.label,False,False,10)
self.hbox1.pack_start
(self.n,False,False,10)
hbox.pack_start(self.hbox1,
False,False,40)

vtombol=gtk.VButtonBox()
vtombol.set_layout
(gtk.BUTTONBOX_SPREAD)
vtombol.set_spacing(2)

tombol = gtk.Button('_PRINT')
image = gtk.Image()
image.set_from_file
('icon/print.png')
tombol.set_image(image)
tombol.connect("clicked",
self.file, jml)
vtombol.add(tombol)

tombol = gtk.Button('_Keluar')
image = gtk.Image()
image.set_from_file
('icon/keluar.png')
tombol.set_image(image)
tombol.connect('clicked',
self.keluar)
vtombol.add(tombol)
hbox.pack_start(vtombol,
False,False,40)

128
for i in self.data[0]:
Iter=isidata.append()
for j in range(0,jml):
isidata.set
(Iter,j,i[j])
self.view=gtk.TreeView(isidata)
for y in range(1,jml+1):
kolom=gtk.TreeView
Column(self.data[y],
gtk.CellRendererText()
,text=y-1)
kolom.set_sort_column
_id(y)
self.view.append_
column(kolom)
self.view.set_rules_hint(True)

sw = gtk.ScrolledWindow()
sw.set_size_request(0,200)
sw.add(self.view)
verbox = gtk.VBox(True,0)
verbox.pack_start(frame,
False,False,0)
verbox.pack_start(sw,
False,False,0)
self.add(verbox)
self.set_position
(gtk.WIN_POS_CENTER)

self.seleksi=self.view.get_
selection()
self.seleksi.set_mode(gtk.
SELECTION_SINGLE)

self.seleksi.connect
("changed", self.on_seleksi)
self.show_all()

def on_seleksi(self, seleksi):
self.view = seleksi.get_tree_view()
(model, iter)=self.seleksi.get_
selected()
if iter:
info = model.get_value(iter, 0)
self.n.set_text(info)
else:
self.n.set_text('')


129
def keluar(self, tombol):
self.destroy()

def file(self, tombol, jl=0):
a=open('laporan.html','w')
if self.satu.get_active()==True:
if self.n.get_text()=='':
return 0
else:
a.write("<html><body>
\n<h1 align=center>DATA
PROFILE</h1><hr><br>
\n")a.write("<table
border=0 align=center>\n")
j=0
x=0
for i in self.data[0]:
j=j+1
for x in range(0,j):
if self.data
[0][x][0]==
self.n.get_text():
g=self.data[0][x]
x=j
a.write("<tr><td
width=300 align=left>
N I M</td><td width=
300>: %s</td></tr>"%g[0])
a.write("<tr><td
width=300 align=left>
Nama</td><td width=
300>: %s</td></tr>"%g[1])
a.write("<tr><td
width=300 align=left>
Alamat</td><td width=
300>: %s</td></tr>"%g[2])
a.write("<tr><td
width=300 align=left>
Tempat, Tanggal Lahir
</td><td width=200>:
%s,%s</td></tr>"
%(g[3],g[4]))

if g[5]=='t':
s='Pria'
else:
s='Wanita'


130
a.write("<tr><td
width=200 align=left>
Jenis Kelamin</td><td
width=300>: %s</td>
</tr>"%s)
ag=religi(g[6])
a.write("<tr><td
width=300 align=left>
Agama</td><td width=
300>: %s</td></tr>"%ag)
a.write("</table>
</body></html>")
else:
a.write("<html><body>\n<h1
align=center>LAPORAN DATA
PROFILE</h1><hr><br>\n")
a.write("<table border=1
align=center><tr>\n")
for y in range(1,jl+1):
a.write("<td><font
size=2><b>%s<b>
</font></td>"%self.
data[y])
a.write("\n</tr>\n<tr>")
j=0
x=0
f=0
for i in self.data[0]:
j=j+1
for x in range(0,j):
for g in self.data[0][x]:
if f==5:
if g=='t':
g='Pria'
else:
g='Wanita'
if f==6:
g=religi(g)
f=f+1
if f==7:
f=0
a.write("<td>
<font size=2>
%s</font></td>"%g)
a.write("\n</tr>\n<tr>")
x=x+1



131
a.write("\n</tr></table>\n
</body></html>")

a.close()
webbrowser.open("/home/buku/
aplikasi++/laporan.html")

def radio1(self, satu):
self.hbox1.set_sensitive(True)
self.view.set_sensitive(True)
self.set_focus(self.n)

def radio2(self, semua):
self.hbox1.set_sensitive(False)
self.view.set_sensitive(False)

def religi(rlg=''):
change = {'0 ':'Islam','1 ':'Katolik','2 ':
'Protestan','3 ':'Hindu',
'4 ':'Buddha','5 ':'Kepercayaan',
'6 ':'Lain-Lain'}
return change[rlg]

def pesan(a=None,b=None,text=""):
dialog = gtk.MessageDialog(a, gtk.DIALOG_
MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, b,
gtk.BUTTONS_OK, text)
dialog.run()
dialog.destroy()

def kalender(x=gtk.combo_box_new_text(),pilih=
'tanggal'):
if pilih=='tanggal':
for i in range(1,32):
x.append_text(str(i))
elif pilih=='bulan':
for i in range(1,13):
x.append_text(str(i))
else:
for i in range(1950,2501):
x.append_text(str(i))

return x

def pecah(a='', b='', c ='', d=gtk.combo_box_new_text
, e=gtk.combo_box_new_text, f=gtk.combo_box_new_text):
i=0
d.set_active(i)

132
e.set_active(i)
f.set_active(i)
if a[0:1]=='0':
a=a[1:2]
if b[0:1]=='0':
b=b[1:2]
for i in range(0,31):
if a==d.get_active_text():
i=31
else:
d.set_active(i)
for i in range(0,12):
if b==e.get_active_text():
i=12
else:
e.set_active(i)
for i in range(0,1450):
if c==f.get_active_text():
i=1450
else:
f.set_active(i)

def register_stock_icons():
items = [('profile', 'ga da', 0, 0, '')]
gtk.stock_add(items)
items = [('keluar', 'ga da', 0, 0, '')]
gtk.stock_add(items)
items = [('laporan', 'ga da', 0, 0, '')]
gtk.stock_add(items)
items = [('about', 'ga da', 0, 0, '')]
gtk.stock_add(items)

factory = gtk.IconFactory()
factory.add_default()

import os
img_dir = os.path.join(os.path.dirname
(__file__), 'icon')
try:
img_path = os.path.join(img_dir,
'profile.png')
pixbuf1 = gtk.gdk.pixbuf_new_from_
file(img_path)
transparent = pixbuf1.add_alpha(True,
chr(255), chr(255),chr(255))
icon_set = gtk.IconSet(transparent)
factory.add("profile", icon_set)


133
img_path = os.path.join(img_dir,
'keluar.png')
pixbuf3 = gtk.gdk.pixbuf_new_from_
file(img_path)
transparent = pixbuf3.add_alpha(True,
chr(255), chr(255),chr(255))
icon_set = gtk.IconSet(transparent)
factory.add("keluar", icon_set)
img_path = os.path.join(img_dir,
'laporan.png')
pixbuf3 = gtk.gdk.pixbuf_new_from_
file(img_path)
transparent = pixbuf3.add_alpha(True,
chr(255), chr(255),chr(255))
icon_set = gtk.IconSet(transparent)
factory.add("laporan", icon_set)
img_path = os.path.join(img_dir,
'about.png')
pixbuf3 = gtk.gdk.pixbuf_new_from_
file(img_path)
transparent = pixbuf3.add_alpha(True,
chr(255), chr(255),chr(255))
icon_set = gtk.IconSet(transparent)
factory.add("about", icon_set)

except gobject.GError, error:
print 'Kesalahan mencari logo toolbar'

def main():
Login()
gtk.main()

if __name__ == '__main__':
main()

Membuat aplikasi server yang diletakkan dan dijalankan


pada komputer server. Aplikasi ini berhubungan langsung
dengandatabaseserver,berikutskripnya:

import SimpleXMLRPCServer
import socket
import pg
import time

class PegawaiXMLRPCServer(SimpleXMLRPCServer.
SimpleXMLRPCServer):
def __init__(self, *args):

134
'''
Constructor class ProfileXMLRPCServer
'''

SimpleXMLRPCServer.SimpleXMLRPCServer.__init__(self,
(args[0], args[1]))
self.ACCESSLIST = ('172.16.0.1',)

def server_bind(self):
'''
Server bind...
'''
self.socket.setsockopt(socket.SOL_
SOCKET, socket.SO_REUSEADDR, 1)
SimpleXMLRPCServer.SimpleXMLRPCServer
.server_bind(self)

def verify_request(self, request, client_
address):
'''
Verifikasi request, hanya IP tertentu
'''
if client_address[0] in self.ACCESSLIST:
return 1
else:
return 0

class Profile:
def __init__(self):
'''
Constructor Class Profile
'''
self.pegawai = ''

def login(self,nilai=[]):
try:
db=pg.DB('tuxhouse',
'localhost',5432,None,None,
nilai[0],nilai[1])
hasil=2
db.close()
except:
hasil=1
return hasil





135
def simpan(self,nilai=[]):
try:
db=pg.DB('tuxhouse',
'localhost',5432,None,None,
'rido','rahasia')
try:
s=1
db.get(nilai[0],
nilai[1],nilai[2])
except:
s=0
if s==1:
hasil=2
else:
kelahiran=nilai[3][5]
+'-'+nilai[3][4]+'-
'+nilai[3][6]
sex = False
if nilai[3][7]==True:
sex=True
db.query("insert into
%s values ('%s','%s',
'%s','%s','%s','%s',
'%s')"%(nilai[0],
nilai[3][0],nilai[3]
[1],nilai[3][2],nilai
[3][3],kelahiran,sex
,nilai[3][8]))
hasil=3
db.close()
except:
hasil=1
return hasil;

def cari(self,nilai=[]):
try:
hasil=[]
db=pg.DB('tuxhouse',
'localhost',5432,None,None,
'rido','rahasia')
try:
s=1
hasil1=db.get(nilai
[0],nilai[1],nilai[2])
except:
s=0
if s==0:
hasil=[2]

136
else:
hasil=[3,hasil1
['nim'],hasil1['nama']
,hasil1['alamat'],
hasil1['tmplahir'],
hasil1['tgllahir'],
hasil1['jk'],hasil1
['agama']]

db.close()
except:
hasil=[1]
return hasil;

def ubah(self,nilai=[]):
try:
db=pg.DB('tuxhouse',
'localhost',5432,None,None,
'rido','rahasia')
try:
s=1
a=db.get(nilai[0],
nilai[1],nilai[2])
if nilai[1]==nilai[3][-1]:
s=2
except:
s=0
if s==1:
hasil=2
else:
kelahiran=nilai[3][5]+'-
'+nilai[3][4]+'-'+nilai[3][6]
sex = False
if nilai[3][7]==True:
sex=True

db.query("update %s set
nim='%s',nama='%s',alamat=
'%s',tmplahir='%s',
tgllahir='%s',jk='%s',
agama='%s' where nim='%s'"
%(nilai[0],nilai[3][0],
nilai[3][1],nilai[3][2],
nilai[3][3],kelahiran,sex,
nilai[3][8],nilai[3][9]))

hasil=3
db.close()

137
except:
hasil=1
return hasil;

def hapus(self,nim):
try:
db=pg.DB('tuxhouse',
'localhost',5432,None,None,
'rido','rahasia')
db.query("delete from profile
where nim='%s'"%(nim))
hasil=2
db.close()
except:
hasil=1
return hasil;

def lapor(self,x,j):
try:
db=pg.DB('tuxhouse',
'localhost',5432,None,None,
'rido','rahasia')
data=db.query("select * from
%s"%x)
db.close()
hasil=[data.getresult()]
for y in range(0,j):
hasil+=[data.fieldname(y)]
except:
hasil=1
return hasil;

server = PegawaiXMLRPCServer('172.16.0.2',2006)
server.register_instance(Profile())
server.serve_forever()

Membuat sebuah file html yang diletakkan pada direktori


program misalkan laporan.html, file ini berfungsi untuk
laporandata.
Mengubah pembacaan PATH browser, dalam hal ini
browserdefaultyangdipakaiadalahMozilla.Padabrowser
pilih menu Edit-Preferences, kemudian pada bagian
NavigatorpilihBlankPage.


138
UjiCobaAplikasi:
CekapakahservicedatabasePostgreSQLtelahberjalan
Jalankanaplikasiserveryangberadapadakomputer
server
Jalankanaplikasiclientyangberadapadakomputerclient

HasilScreenshotTampilanGUl:
TampilanLogin

TampilanMenuUtama


139
TampilanAdministrasiTabelProfile

TampilanMenuLaporanDataProfile


140
TampilanLaporanDataProfileperrecorddenganbrowser
mozilla

TampilanLaporanseluruhDataProfile


141
Catatan:
Jika resource yang tersedia hanya 1 komputer jangan bersedih
dahulu karena aplikasi di atas bisa dimanipulasi untuk berjalan
pada1komputer.Caranya:

Padaaplikasiclientgantiskripdibawahini:

kirim=xmlrpclib.Server('http://172.16.0.2:2006')
menjadi:

kirim=xmlrpclib.Server('http://127.0.0.1:2006')
PadaaplikasiservergantibagianACCESSLlST:

self.ACCESSLIST = ('172.16.0.1',)

menjadi:

self.ACCESSLIST = ('127.0.0.1',)

Danbagiandeklarasiserver:

server = PegawaiXMLRPCServer('172.16.0.2',2006)
menjadi:

server = PegawaiXMLRPCServer('127.0.0.1',2006)


142

Buku yang judulnya terdengar aneh ini dibuat bukan


tanpa dasar yang jelas. Awal mulanya ketika penulis
tertarik untuk mencoba belajar suatu bahasa
pemograman yang namanya sangat menyeramkan
disebut Python. Dalam masa belajar dan mencoba-coba
itulah penulis semakin keranjingan untuk belajar lebih
banyaktentangPython.Halutamayangmembuatpenulis
ingin mengacungkan jempol pada bahasa ini adalah
tersedianyabanyakmoduleprogramdariyangsederhana
hingga yang komplek. Karena itu mengapa judul yang
dipilih untuk buku ini adalah Python++. Disini akan
dijelaskan sisi "++ dari bahasa Python secara aplikatif
sepertiimplementasiGUldenganmoduleGTK,database
dengan module PostgreSQL, dan distributed system
denganmoduleXMLRPC.

Penasaran??? Silahkan nikmati sajian "++ dari buku ini,


semogamenjadibermanfaat.
Mahdi Ridho, seorang mahasiswa STMlK AMlKOM
YogyakartainilahirdiJembertahun1985.Bergabung
dalam komunitas Kelompok Studi GNU/Linux
AMlKOM sejak tahun 2004 dan juga pernah aktif di
dalam keanggotaan Kelompok Pengguna Linux
lndonesia wilayah Yogyakarta. Mahasiswa yang
sering dipanggil "rochem ini pernah menulis buku
berjudul "Pemograman Gambas, Pemograman ala
VisualBasicdiLinux.