Py PG Database PDF
Py PG Database PDF
©2012
Daftar Isi
1 Alasan 5
2 Pemasangan 6
3 Hello World! 9
3.1 Variabel dan Tipe Datanya . . . . . . . . . . . . . . . . . . . . . 10
3.2 Kondisi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.3 Perulangan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
4 Tipe Data 17
4.1 String . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.2 Bilangan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
4.2.1 Konversi Tipe Data . . . . . . . . . . . . . . . . . . . . . 19
4.2.2 Formatting . . . . . . . . . . . . . . . . . . . . . . . . . . 19
4.2.3 Kalkulator . . . . . . . . . . . . . . . . . . . . . . . . . . 20
4.3 List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
4.3.1 Pemenggalan . . . . . . . . . . . . . . . . . . . . . . . . . 21
4.3.2 Keberadaan Elemen . . . . . . . . . . . . . . . . . . . . . 22
4.3.3 Mengubah Elemen . . . . . . . . . . . . . . . . . . . . . . 25
4.4 Di
tionary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
4.5 Waktu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
5 Modularitas 31
5.1 Membuat Fungsi . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
5.2 Membuat Modul . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
5.3 Sear
h Path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
6 Fungsi 37
6.1 Memanggil Dirinya Sendiri . . . . . . . . . . . . . . . . . . . . . 37
6.2 Format Uang . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
7 Database 42
7.1 Tabel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
7.1.1 Sequen
e . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
7.1.2 Mengubah Struktur . . . . . . . . . . . . . . . . . . . . . 49
1
DAFTAR ISI 2
7.2 View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
7.3 Ba
kup dan Restore . . . . . . . . . . . . . . . . . . . . . . . . . 53
7.3.1 En
oding . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
7.4 Fungsi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
7.4.1 PL/pgSQL . . . . . . . . . . . . . . . . . . . . . . . . . . 56
7.4.2 PL/Python . . . . . . . . . . . . . . . . . . . . . . . . . . 61
9 Lintas Sistem 80
9.1 Command Line . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
9.2 File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
9.3 Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
9.4 XMLRPC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
9.4.1 PHP sebagai XMLRPC Client . . . . . . . . . . . . . . . 87
9.4.2 Drupal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
10 Pengemasan 90
10.1 Paket Debian . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
10.2 Debian Repository . . . . . . . . . . . . . . . . . . . . . . . . . . 95
10.3 Remastering Ubuntu . . . . . . . . . . . . . . . . . . . . . . . . . 96
15 Web 124
15.1 Django . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
15.2 Webpy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
16 Hosting 125
16.1 Virtualmin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
16.1.1 Pemasangan Ubuntu . . . . . . . . . . . . . . . . . . . . . 125
16.1.2 Kongurasi Network . . . . . . . . . . . . . . . . . . . . . 126
16.1.3 Pemasangan Virtualmin . . . . . . . . . . . . . . . . . . . 127
16.1.4 Text Editor . . . . . . . . . . . . . . . . . . . . . . . . . . 128
16.1.5 Kongurasi PHP . . . . . . . . . . . . . . . . . . . . . . . 129
16.1.6 Mail Server . . . . . . . . . . . . . . . . . . . . . . . . . . 129
16.1.7 PostgreSQL . . . . . . . . . . . . . . . . . . . . . . . . . . 130
16.1.8 Kongurasi Awal Virtualmin . . . . . . . . . . . . . . . . 130
16.1.9 Mail A
ount . . . . . . . . . . . . . . . . . . . . . . . . . 131
16.1.10 Hak Akses . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
16.1.11 Berikan Bash . . . . . . . . . . . . . . . . . . . . . . . . . 132
16.1.12 Kongurasi Python . . . . . . . . . . . . . . . . . . . . . . 132
16.1.13 Mengubah Sifat Virtualmin . . . . . . . . . . . . . . . . . 133
16.1.14 Pendaftaran Domain . . . . . . . . . . . . . . . . . . . . . 138
16.1.15 User Spa
e . . . . . . . . . . . . . . . . . . . . . . . . . . 139
16.2 Google Apps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
Kata Pengantar
Terimakasih saya u
apkan untuk I Made Wiryana yang telah mengusulkan
Python kepada penulis untuk pertama kali. Juga kepada Arie Zanahar yang
mengusulkan penggunaan Virtualmin sebagai hosting management.
4
Bab 1
Alasan
Mengapa Python merupakan bahasa yang tepat untuk pembuatan berbagai
aplikasi ? Berikut ini alasannya.
Mudah Python tergolong s
ripting, artinya Anda
ukup tulis sour
e-nya di
text editor biasa, lalu jalankan.
Hemat Bahasa ini berkonsep hemat sour
e. Tampak pada
ara penulisannya
yang tidak membutuhkan karakter atau kata khusus untuk BEGIN dan
END. Sebagai gantinya sub-blo
k dipisahkan dengan indent (penulisan
menjorok ke kanan).
5
Bab 2
Pemasangan
Untuk memudahkan penjelasan, kita gunakan distro Linux berbasis Ubuntu.
Pada saat tulisan ini dibuat kami menggunakan Ubuntu 10.04 (Lu
id). Anda
juga bisa menggunakan jenis Ubuntu lainnya seperti Kubuntu (window manager
KDE), atau BlankOn (buatan Indonesia).
Pas
a instalasi Ubuntu Python sudah disertakan. Namun masih ada yang
perlu diunduh (download) lagi. Sebelumnya perbaharui daftar paket yang akan
diunduh, lakukan ini di konsole:
1 $ sudo a p t −g e t update
Pasang PostgreSQL:
Se
ara default Apa
he hidup otomatis saat komputer boot. Lalu buatlah sym-
link phppgadmin:
6
BAB 2. PEMASANGAN 7
http://lo alhost/phppgadmin
Bagi pengguna window manager Gnome Anda bisa gunakan gedit sebagai text
editor. Sedangkan pengguna KDE bisa gunakan kate. Keduanya berbasis GUI.
Jika Anda lebih nyaman dengan konsole bisa gunakan nano, joe, atau vi.
1 $ sudo vi / e t / vim / v i m r
Saat Anda membuka le untuk keduakalinya, maka kursor langsung menuju
ke lokasi sebelumnya.
Menjorok otomatis (auto indent), dan penekanan tombol TAB diganti den-
gan SPACE 4 kali:
Bila kata yang di
ari mengandung huruf besar dan huruf ke
il, maka pen-
arian memperhatikan huruf besar atau ke
il (
asesensitive).
Aktifkan kedua opsi pen
arian di atas, maka pen
arian di vim ( menggu-
nakan perintah slash / ) semakin mudah.
Bab 3
Hello World!
Anda bisa memulai Python dalam modus interaktif. Nanti kalau sour
e sudah
mulai panjang kita simpan dalam le. Modus interaktif dijalankan di konsole,
lalu ketik:
1 $ python
Gunakan tombol panah atas untuk mengulang perintah sebelumnya, lalu ki-
ta
oba sedikit salah satu
iri pemgrograman berorientasi objek (obje
t oriented
programming / OOP).
'Hello World!' adalah sebuah string, yaitu DATA yang boleh berisi alphanu-
meri
, boleh terdiri dari huruf dan angka atau karakter lainnya. Contoh di atas
menyebutkan bahwa string tidak hanya berisi data, ia juga memuat FUNGSI
yang bernama upper() dan lower(). Dengan demikian 'Hello World!' bukan
sekedar string, tapi disebut OBJEK string. Inilah
iri objek, memuat data dan
fungsi.
9
BAB 3. HELLO WORLD! 10
Selain menggunakan kutip tunggal, string juga dapat dibatasi oleh kutip ganda:
Bila string lebih dari satu baris Anda bisa gunakan kutip tiga kali:
Perhatikan tiga buah titik di atas yang berarti sebuah perintah belum be-
rakhir.
Selanjutnya marilah membuat s
ript yang akan menanyakan nama, alamat,
dan hobi, lalu menampilkannya kembali di layar. Kali ini kita simpan dalam
sebuah le pegawai.py. Anda bisa gunakan text editor favorit seperti gedit,
kate, nano, joe, atau vi.
1 $ python p e g a w a i . py
raw_input() adalah fungsi untuk menerima masukkan dari user. Fungsi ini
menghasilkan string yang berisi masukkan user tersebut, dan dilimpahkan ke
variabel nama, alamat, dan hobi. Anda bisa kembali ke modus interaktif untuk
sekedar mengetahui tipe data dari variabel nama.
BAB 3. HELLO WORLD! 11
Pada s
ript di atas kita mulai mengenal apa yang disebut variabel, yaitu
nama, alamat, dan hobi. Variabel bisa dikatakan sebagai penampung. Tipe
data ketiga variabel di atas adalah string. Mari kita
oba tipe data lainnya.
1 >>> a = 3
2 >>> b = 5
3 >>> p r i n t a + b
4 8
5 >>> p r i n t type ( a )
6 <t y p e ' i n t '>
Variabel a dan b bertipe integer alias bilangan bulat. Berikut ini untuk
bilangan pe
ahan (oat).
1 >>>
= 7 . 2
2 >>> p r i n t type (
)
3 <t y p e ' f l o a t '>
Ya, pemisah bilangan bulat dengan pe
ahannya adalah dengan titik. Oh ya,
Python tergolong ketat dalam hal pengoperasian antar tipe data. Kita tidak
diperkenankan menambahkan string dengan integer.
Meski string tidak bisa ditambah dengan integer, namun string bisa dikalikan
dengan integer:
Kemudian jalankan:
1 $ python p e g a w a i . py
hasilnya Python protes karena ada indent (menjorok masuk) yang tidak
diperkenankan:
1 $ python p e g a w a i . py
2 File " p e g a w a i . py " , line 6
3 print ' Hobi : ', hobi
4 ^
5 IndentationError : unexpe
ted indent
Seperti kita lihat, s
ript Python tanpa diawali suatu BEGIN .. END atau
{ .. } atau berbagai penanda lainnya sebagai bentuk awal dan akhir program.
Baris-baris utama selalu tanpa indent alias rapat kiri. Baris yang memiliki
indent berarti dianggap bagian dari sub-blok seperti dalam looping (for) atau
kondisi (if ).
3.2 Kondisi
Python punya sema
am pedoman dalam hal kondisi (if ), dimana jika suatu
variabel ada isinya maka True, jika kosong maka False.
1 if hobi :
2 print ' Hobi : ', hobi
Se
ara tipe data hobi tentulah sebuah string, tapi bagaimana dengan hobi
!= ? Mari kita uji di modus interaktif dimana variabel hobi ada isinya.
BAB 3. HELLO WORLD! 13
1 >>> h o b i = ''
2 >>> h o b i != ''
3 False
4 >>> h o b i == ''
5 True
1 >>> k o s o n g = h o b i == ''
2 >>> p r i n t kosong
3 True
Kembali ke pegawai.py dimana bila hobi tidak diisi maka program akan
memberikan saran. Salinlah menjadi pegawai1.py seperti berikut ini.
Perhatikan juga penggunaan titik dua ( : ) pada if dan else. Ini
iri lain
untuk menandai awal suatu sub-blok. Jadi bisa dipastikan setelah titik dua
baris berikutnya selalu menjorok ke dalam (indent).
3.3 Perulangan
Mari kita buat input pegawai jadi lebih mudah, dimana program akan menanyakan
data terus-menerus dan baru berhenti bila nama tidak diisi.
1 while True :
2 nama = r a w _ i n p u t ( ' Nama : ')
3 if not nama :
4 break
5 a l a m a t = r a w _ i n p u t ( ' Alamat : ')
6 h o b i = r a w _ i n p u t ( ' Hobi : ')
7 print ' Nama : ' , nama
8 print ' Alamat : ' , alamat
9 if hobi :
10 print ' Hobi : ' , hobi
11 else :
12 print ' Sebaiknya hobi diisi . '
Perhatikan baris pertama yang berarti perulangan tanpa henti. Yang menghen-
tikannya adalah baris ke empat. break adalah kata khusus untuk menghentikan
perulangan dimana alur keluar menuju blok bawah di luar perulangan tersebut.
Kebetulan dalam
ontoh ini tidak ada blok lain di luar perulangan.
Selanjutnya kita buat aturan baru untuk pengisian data ini, dimana:
2. Bila selesai satu data pegawai maka program akan menanyakan apakah
akan memasukkan data berikutnya.
BAB 3. HELLO WORLD! 15
1 for i in [1 ,2 ,3 ,4 ,5℄:
2 print i
Hasilnya:
1
2
3
4
5
Perhatikan [1,2,3,4,5℄ yang merupakan data bertipe list atau sering juga disebut
sebagai array. Kita bisa persingkat penulisannya dengan fungsi range().
1 for i in range ( 5 ) :
2 print i
Hasilnya
BAB 3. HELLO WORLD! 16
0
1
2
3
4
Meski tidak dimulai dari 1 tapi jumlah barisnya tetap 5. Jika tetap ingin dimulai
dari 1 gunakan range(1,6).
1 for i in range ( 1 , 6 ) :
2 print i
Tipe Data
Memperhatikan tipe data salah satu pokok pada Python dan ini juga menjadi
salah satu kun
i agar mudah dalam pen
arian kesalahan (debugging).
4.1 String
Masih belum yakin apa tipe data variabel nama ? Gunakan type().
1 >>> t y p e ( nama )
2 <t y p e ' s t r '>
Data bertipe string bisa berisi karakter apa saja seperti huruf, angka, tanda
ba
a, atau gabungannya.
Menggabungkan dua buah variabel string bisa menggunakan tanda plus ( +
).
Namun
ara ini tidak disarankan karena membuat program menjadi sulit
diba
a. Kalau program sulit diba
a menyulitkan penelusuran bila ada kesalahan
(debugging). Jadi sebaiknya gunakan formatting.
17
BAB 4. TIPE DATA 18
4.2 Bilangan
Bilangan bulat atau integer atau disingkat int dinyatakan tanpa titik.
1 >>> a = 1 0
a ditambah 2
1 >>> a + 2
2 12
a dikurang 4
1 >>> a − 4
2 6
a dikali 5
1 >>> a * 5
2 50
a dibagi dengan 3
1 >>> a / 3
2 3
1 >>> a / 3.0
2 3.3333333333333335
1 >>> a % 3
2 1
a pangkat 2
1 >>> a ** 2
2 100
BAB 4. TIPE DATA 19
1 >>> i n t ( 1 0 . 2 )
2 10
1 >>> r o u n d ( 1 0 . 4 )
2 10
3 >>> r o u n d ( 1 0 . 5 )
4 11
4.2.2 Formatting
Menuliskan bilangan ke dalam string bisa menggunakan formatting.
1 >>> a = 3
2 >>> b = 2
3 >>> p r i n t '% s + %s = %s ' % ( a , b, a+b )
4 3 + 2 = 5
Meski formatting %s bisa digunakan untuk tipe data apa saja, sebaiknya An-
da menggunakan formatting yang lebih spesik sesuai tipe datanya. Katakanlah
Anda menetapkan bahwa variabel a itu harus bertipe bilangan bulat (integer),
begitu pula dengan variabel b, maka gunakanlah %d.
1 >>> a = 3 . 5
2 >>> p r i n t '% f + %f = %f ' % ( a , b, a+b )
3 3.500000 + 2.000000 = 5.500000
4.2.3 Kalkulator
Membuat kalkulator tidaklah sulit, Anda
ukup gunakan eval(). Buatlah le
al
.py berikut ini.
1 while True :
2 h i t u n g = raw_input ( ' Hitung : ')
3 if not hitung :
4 break
5 print eval ( hitung )
Jalankan.
1 $ python
a l
. py
2 Hitung : 2+3
3 5
4 Hitung : 7 ** 2
5 49
6 Hitung : 7 + 2 * 3
7 13
8 Hitung :
9 $
4.3 List
Tipe data list kerap digunakan. Kita lihat pada
ontoh sebelumnya bagaimana
list menjadi wajib pada perulangan for. Bahkan string sebenarnya bisa dianggap
sebagai list.
hasilnya:
1 Bummi
Perhatikan penggunaan koma pada print yang berarti jangan ganti baris.
Mari kembali ke modus interaktif untuk men
oba list.
BAB 4. TIPE DATA 21
1 >>> d a t a = [ ' Bummi Dwi P u t e r a ' , ' Bogor ' , ' Menggambar ' , 2 4 ℄
2 >>> p r i n t data [ 0 ℄
3 ' Bummi Dwi Putera '
4 >>> p r i n t data [ 1 ℄
5 ' Bogor '
4.3.1 Pemenggalan
Selain dapat diambil per elemen, juga dapat diambil beberapa elemen sekali-
gus, ini disebut sebagai pemenggalan (sli
ing). Tampilkan elemen pertama dan
kedua:
1 >>> p r i n t data [ 0 : 2 ℄
2 [ ' Bummi Dwi Putera ' , ' Bogor ' ℄
1 >>> p r i n t data [ : 2 ℄
2 [ ' Bummi Dwi Putera ' , ' Bogor ' ℄
Ada baiknya kita pahami
ara kerjanya. Pemenggalan list bekerja dengan
batas elemen. Gambar 4.1 adalah
ontoh string Python yang bisa dianggap
sebagai list. Cermati baik-baik bagaimana bekerja dengan elemen dan batas
elemen (untuk pemenggalan).
BAB 4. TIPE DATA 22
1 d a f t a r = [ ' j e r u k ' , ' mangga ' , ' a p e l ' , ' p i s a n g ' , ' jambu ' ℄
2
3 while True :
4
a r i = raw_input ( ' C a r i buah : ')
5 if not
ari :
6 print ' Selesai '
7 break
8 if in
ari daftar :
9 print ( ' Ditemukan ' )
10 else :
11 print ( ' Tidak ditemukan ' )
Jalankanlah.
1 $ python p r o d u k . py
2 Cari buah : mangga
3 Ditemukan
4 Cari buah : duku
5 Tidak ditemukan
6 Cari buah :
7 Selesai
1 import sys
2 print sys . argv
Jalankanlah.
1 $ python
a t . py
2 [ '
a t . py ' ℄
Perhatikan elemen pertama adalah le
at.py itu sendiri, dan elemen kedua
adalah nama le yang akan ditampilkan. Ya, kita akan membuatnya dapat
membuka le yang disebutkan dan menampilkannya di layar.
BAB 4. TIPE DATA 23
1 import sys
2
3 f i l e n a m e = sys . argv [ 1 ℄
4 f = open ( f i l e n a m e )
5 print f . read ( )
6 f .
lose ()
Jalankan.
Kita perlu mengantisipasi kesalahan yang dilakukan user, dimana bisa saja
ia tidak tahu
ara menggunakan
at1.py, yaitu langsung menjalankan tanpa
menyertakan nama le.
1 $ python
a t 1 . py
2 Tra
eba
k ( most re
ent
all last ) :
3 File "
a t . py " , line 3, i n <module>
4 f i l e n a m e = sys . argv [ 1 ℄
5 IndexError : list index out of range
Tampilan kesalahan ini jelas kurang informatif dan bisa jadi user tidak tahu
apa yang harus dilakukan. Saatnya menggunakan deteksi keberadaan elemen.
1 import sys
2
3 if not sys . argv [ 1 : ℄ :
4 print ( ' Cara menggunakannya : p y t h o n %s <nama− f i l e > ' %
sys . argv [ 0 ℄ )
5 sys . exit ()
6
7 f i l e n a m e = sys . argv [ 1 ℄
8 f = open ( f i l e n a m e )
9 print f . read ( )
10 f .
lose ()
BAB 4. TIPE DATA 24
1 $ python
a t 2 . py
2 Cara menggunakannya : python
a t . py <nama− f i l e >
if not sys.argv[1:℄:
Kalau kita perhatikan lagi isi dari sys.argv pada saat tidak diberikan input
parameter adalah:
[' at.py'℄
[℄
if not sys.argv[1:℄:
bisa berarti
if not [℄:
yang berarti
if not False:
if True:
True berarti kondisi terpenuhi dan blok di dalam if dijalankan, dan akhirnya
tampillah pesan
ara penggunaan
at2.py tadi.
Lalu apa yang terjadi jika program mendapat input parameter ? Nilai
sys.argv menjadi
Dengan begitu
if not sys.argv[1:℄:
bisa berarti
Karena ['/et
/hosts'℄ adalah list yang berisi (tidak hampa) maka bisa dianggap
sebagai boolean True
if not True:
if False:
False berarti kondisi tidak terpenuhi sehingga blok di dalam if tidak dijalankan.
Pahamilah baik-baik penjelasan ini, Anda akan banyak menemuinya nanti.
Inilah salah satu mengapa program yang dibuat dengan Python begitu ringkas
namun tetap mudah diba
a.
1 >>> d a f t a r = [℄
2 >>> d a f t a r
3 [℄
Tambahkan mangga.
Kita akan ubah elemen kedua (index ke 1) dari pisang menjadi jeruk.
1 >>> d e l daftar [ 0 ℄
2 >>> d a f t a r
3 [ ' jeruk ' ℄
BAB 4. TIPE DATA 26
4.4 Di tionary
List adalah serangkaian elemen yang alamatnya adalah nomor urut, sering
disebut sebagai index. Di
tionary juga mirip, hanya saja alamatnya tidak harus
berupa angka yang berurutan. Bahkan bisa bertipe string atau tipe data lain-
nya. Sekarang buatlah s
ript berikut ini.
1 daftar = {
2 2: ' jeruk ' ,
3 7: ' mangga ' ,
4 4: ' pisang ' ,
5 3: ' jambu ' ,
6 9: ' apel ' ,
7 }
8
9 print daftar
Jalankan.
1 $ python p r o d u k 1 . py
2 {9: ' apel ' , 2: ' jeruk ' , 3: ' jambu ' , 4: ' pisang ' , 7: '
mangga ' }
Perhatikan urutan pada sour
e, dan bandingkan urutan buah saat dita-
mpilkan. Begitulah di
tionary, dia memang tidak memperhatikan urutan. Ini-
lah salah satu yang membedakannya dengan list. Di
tionary
o
ok untuk pen-
arian. Pada
ontoh di atas angka 2, 7, 4, 3, dan 9 merupakan kun
i (key)
bagi variabel daftar. Key ini bisa saja dianggap sebagai kode barang atau kode
buah. Sedangkan apel, jeruk, jambu, pisang, dan mangga merupakan nilai (val-
ue). Karena itu di
tionary sering disebut sebagai tipe data dengan formasi key
value.
Sekarang kita buat pen
arian berdasarkan kode barang.
1 daftar = {
2 2: ' jeruk ' ,
3 7: ' mangga ' ,
4 4: ' pisang ' ,
5 3: ' jambu ' ,
6 9: ' apel ' ,
7 }
8
9 while True :
10 k e y = r a w _ i n p u t ( ' Kode barang : ')
11 if not key :
12 print ' Selesai '
13 break
BAB 4. TIPE DATA 27
14 if key in daftar :
15 print d a f t a r [ key ℄
16 else :
17 print ' Kode barang ' , key , ' tidak ditemukan '
Cobalah.
1 $ python p r o d u k 2 . py
2 Kode barang : 5
3 Kode barang 5 tidak ditemukan
4 Kode barang : 9
5 Kode barang 9 tidak ditemukan
6 Kode barang :
7 Selesai
Kode barang 5 boleh jadi tidak ditemukan, karena memang tidak ada 5
dalam variabel daftar. Tapi mengapa 9 juga tidak ditemukan ? Seharusnya
program menampilkan apel.
Jawabannya ada pada tipe data. Fungsi raw_input() itu mengembalikan
nilai bertipe string. Berarti key pada baris
if key in daftar:
berarti men
ari string key dalam daftar yang isinya bilangan bulat (integer)
semua, yaitu 2, 7, 4, 3, dan 9. Jelas tidak akan ditemukan. Untuk membuktikan
bahwa key itu adalah string ubahlah sedikit pada baris terakhir
menjadi
1 $ python p r o d u k 2 . py
2 Kode barang : 9
3 Kode barang [ '9 '℄
4 tidak ditemukan
5 Kode barang :
6 Selesai
Dengan memberikan kurung siku pada variabel maka akan tampak bahwa
key adalah string. Terlihat adanya kutip tunggal pada '9'. Lalu bagaimana
mengubah key agar bertipe integer ? Gunakan fungsi int().
BAB 4. TIPE DATA 28
1 daftar = {
2 2: ' jeruk ' ,
3 7: ' mangga ' ,
4 4: ' pisang ' ,
5 3: ' jambu ' ,
6 9: ' apel ' ,
7 }
8
9 while True :
10 k e y = r a w _ i n p u t ( ' Kode barang : ')
11 if not key :
12 print ' Selesai '
13 break
14 key = i n t ( key )
15 if in
key daftar :
16 print d a f t a r [ key ℄
17 else :
18 print ' Kode barang ' , key , ' tidak ditemukan '
Jalankan lagi.
1 $ python p r o d u k 3 . py
2 Kode barang : 5
3 Kode barang [5℄ tidak ditemukan
4 Kode barang : 9
5 apel
6 Kode barang :
7 Selesai
Resapi kembali mengenai tipe data ini karena akan sering dijumpai nanti.
4.5 Waktu
Modul time digunakan untuk penanganan waktu. Kita kembali ke modus inter-
aktif dulu untuk memudahkan latihan.
1 >>> i m p o r t time
2 >>> t = t i m e . l o
a l t i m e ( )
3 >>> t
4 t i m e . s t r u
t _ t i m e ( tm_year = 2 0 1 0 , tm_mon=8 , tm_mday=20 ,
tm_hour =11 , tm_min=44 , tm_se
=47 , tm_wday=4 , tm_yday
=232 , t m _ i s d s t =0)
Fungsi time.lo
altime() digunakan untuk mendapatkan waktu saat ini. Per-
hatikan variabel t di atas. Jika Anda ingin mengambil tahunnya:
1 >>> t . tm_year
2 2010
BAB 4. TIPE DATA 29
atau bulannya
1 >>> t . tm_mon
2 8
atau harinya
1 >>> t . tm_mday
2 20
1 >>> t i m e . t i m e ( )
2 1282280699.2280381
Epo
h ini adalah jumlah detik sejak 1 Januari 1970 jam 00:00:00 (GMT)
hingga saat ini.
Fungsi time.lo
altime() sebenarnya bisa diberikan masukan berupa epo
h
ini. Kita bisa mulai dengan angka 0.
1 >>> t i m e . l o
a l t i m e ( 0 )
2 t i m e . s t r u
t _ t i m e ( tm_year = 1 9 7 0 , tm_mon=1 , tm_mday=1 ,
tm_hour=7 , tm_min=0 , tm_se
=0 , tm_wday=3 , tm_yday=1 ,
t m _ i s d s t =0)
1 >>> t i m e . mktime ( ( 2 0 1 0 , 8 , 1 7 , 0 , 0 , 0 , 0 , 0 , 0 ) )
2 1281978000.0
Dengan epo
h kita bisa mendapatkan jumlah hari sejak 1 Agustus 2010
hingga 17 Agustus 2010.
1 >>> a w a l = t i m e . mktime ( ( 2 0 1 0 , 8 , 1 , 0 , 0 , 0 , 0 , 0 , 0 ) )
2 >>> a k h i r = t i m e . mktime ( ( 2 0 1 0 , 8 , 1 7 , 0 , 0 , 0 , 0 , 0 , 0 ) )
3 >>> a k h i r − awal
4 1382400.0
Itu adalah jumlah detiknya. Untuk mendapatkan hari kita perlu mengolah-
nya kembali.
1 >>> ( a k h i r − awal ) / 24 / 60 / 60
2 16.0
Modul datetime
Menghitung hari lebih mudah menggunakan modul datetime.
Dengan modul ini kita juga dapat menghitung jumlah detik sejak 16 Agustus
2010 jam 22:00 hingga 17 Agustus 2010 jam 10:00.
1 >>> d . s e
o n d s / 60 / 60
2 12
Bab 5
Modularitas
Mari kita buat program yang menghitung nilai faktorial. Apa itu faktorial ?
Berikut ini
ontohnya:
5! = 5 * 4 * 3 * 2 * 1 = 120
4! = 4 * 3 * 2 * 1 = 24
3! = 3 * 2 * 1 = 6
2! = 2 * 1 = 2
1! = 1
0! = 1
-1! = 1
Dengan demikian rumus faktorial memiliki ketentuan:
2. n! = n * (n-1)!
Selanjutnya kita akan buat program yang akan menanyakan nilai n dan menampilkan
nilai faktorial-nya.
31
BAB 5. MODULARITAS 32
Jalankan.
1 $ python f a k t o r i a l 1 . py
2 Menghitung nilai faktorial
3 n = 2
4 2! = 2
5 n = 3
6 3! = 6
7 n = 4
8 4 ! = 24
9 n =
10 $
15 n = int (n)
16 h a s i l = f a k t o r i a l (n)
17 print '%d ! = %d ' % ( n , hasil )
Jalankan.
1 $ python f a k t o r i a l 2 . py
2 Menghitung nilai faktorial
3 n = 5
4 5 ! = 120
5 n = 2
6 2! = 2
7 n = 1
8 1! = 1
9 n = −1
10 − 1! = 1
11 n =
Hasilnya memang sama saja, namun kini sour
e faktorial lebih mudah diba
a
dan di-
opy-paste. Perhatikan juga penggunaan return yang membuat alur
keluar dari fungsi.
Apa ini sudah
ukup modular ? Jawabannya belum.
Copy-paste sour
e seperti itu tentu saja lebih sulit ketimbang
opy-paste le-
nya. Oleh karena itu Anda perlu membuat sour
e itu menjadi modul faktorial
yang berarti namanya menjadi faktorial.py sehingga program lain yang mem-
butuhkannya
ukup menggunakannya seperti ini (
ontoh):
2
3 print ' Menghitung nilai faktorial '
4 while True :
5 n = raw_input ( ' n = ')
6 if not n:
7 break
8 n = int (n)
9 h a s i l = f a k t o r i a l (n)
10 print '%d ! = %d ' % ( n , hasil )
Jalankan.
1 $ python
o b a f a k t o r i a l . py
2 Menghitung Nilai Faktorial
3 n = 5
4 5 ! = 120
5 n = 2
6 2! = 2
7 n =
Hasilnya tetap sama, namun kini Anda lebih mudah
opy-paste sour
e fungsi
faktorial() karena
ukup faktorial.py yang di-
opy ke direktori program lainnya.
Untuk men
oba modul faktorial Anda perlu membuat le lainnya yaitu
obafaktorial.py. Agar lebih praktis, mengapa tidak disatukan saja ?
Benar, alangkah praktisnya jika sour
e untuk menguji fungsi faktorial() juga
berada di le yang sama.
Namun Anda perlu membuat sedikit perubahan agar saat
sour
e uji
oba tersebut tidak dijalankan. Silahkan ubah faktorial.py menjadi
berikut ini.
Perhatikan bahwa __name__ adalah name yang diawali dan diakhiri oleh
dua unders
ore. Begitu juga dengan __main__. Kemudian jalankan.
1 $ python f a k t o r i a l . py
2 Menghitung nilai faktorial
3 n = 3
4 3! = 6
5 n = 4
6 4 ! = 24
7 n =
if __name__ == '__main__':
Dengan baris ini Python diberitahu bahwa sour
e dibawahnya hanya dijalankan
jika faktorial.py merupakan program utama. Kalau faktorial.py sebagai modul
maka ia tidak dijalankan.
Anda juga masih bisa menggunakan
obafaktorial.py seperti biasa.
1 $ python o b a f a k t o r i a l . py
1 >>> i m p o r t sys
2 >>> s y s . p a t h
3 [ ' ' ,
4 ' / u s r / l i b / python2 . 6 ' ,
5 ' / u s r / l i b / p y t h o n 2 . 6 / p l a t −l i n u x 2 ' ,
6 ' / u s r / l i b / python2 . 6 / l i b −t k ' ,
7 ' / u s r / l i b / python2 . 6 / l i b −o l d ' ,
8 ' / u s r / l i b / p y t h o n 2 . 6 / l i b −d y n l o a d ' ,
9 ' / u s r / l i b / p y t h o n 2 . 6 / d i s t −p a
k a g e s ' ,
10 ' / u s r / l i b / p y t h o n 2 . 6 / d i s t −p a
k a g e s / PIL ' ,
11 ' / u s r / l i b / p y t h o n 2 . 6 / d i s t −p a
k a g e s / g s t − 0 . 1 0 ' ,
12 ' / u s r / l i b / pymodules / python2 . 6 ' ,
13 ' / u s r / l i b / p y t h o n 2 . 6 / d i s t −p a
k a g e s / g t k
−2.0 ' ,
14 ' / u s r / l i b / pymodules / python2 . 6 / gtk −2.0 ' ,
15 ' / u s r / l o
a l / l i b / p y t h o n 2 . 6 / d i s t −p a
k a g e s ' ℄
BAB 5. MODULARITAS 36
Pertama kali Python akan men
ari di direktori dimana program utama be-
rada. Selanjutnya ia akan men
ari di direktori lainnya seperti yang Anda lihat
di atas.
Lalu dimana sebaiknya faktorial.py diletakkan ? Karena meletakkannya
tidak melalui instalasi paket Debian, maka saya sarankan diletakkan di direktori
1 $ sudo
p f a k t o r i a l . py / u s r / l o
a l / l i b / python2 . 6 / d i s t −
pa
kages
1 $ s u d o mv f a k t o r i a l . py / u s r / l o
a l / l i b / python2 . 6 / d i s t −
pa
kages
Jika Anda punya direktori lain, Anda bisa tambahkan pada sys.path terlebih
dahulu sebelum import.
1 >>> i m p o r t sys
2 >>> s y s . p a t h . append ( ' / home / s u g i a n a / l i b ' )
3 >>> f r o m faktorial import faktorial
Bab 6
Fungsi
Fungsi faktorial() sudah bekerja dengan baik. Tapi mungkin sour
e-nya terlalu
panjang. Cobalah ubah menjadi seperti di bawah ini pada faktorial.py.
Jauh lebih esien bukan? Teknik seperti ini disebut juga sebagai rekursif.
Pertama kali yang harus diperhatikan dalam pembuatan fungsi rekursif adalah
batas kedalaman. Batas ini ditunjukkan pada baris 2-3. Rekursif yang tidak
memiliki batas kedalaman akan menampilkan pesan kesalahan.
1 >>> i m p o r t lo
ale
2 >>> l o
a l e . s e t l o
a l e ( l o
a l e . LC_ALL, ' id_ID . UTF− 8 ' )
3 ' id_ID . UTF8 '
4 >>> l o
a l e . format ( '%.2 f ' , 10000 , True )
5 '10.000 ,00 '
Namun jika saat setlo ale Anda menjumpai pesan kesalahan seperti ini:
37
BAB 6. FUNGSI 38
Karena uang() adalah fungsi umum yang akan banyak digunakan di berbagai
program, ada baiknya kita simpan sebagai modul bernama uang.py.
1 import lo
ale
2 l o
a l e . s e t l o
a l e ( l o
a l e . LC_ALL, ' id_ID . UTF−8 ' )
3
4
5 def uang ( n i l a i , p e
a h a n =2) :
6 return l o
a l e . f o r m a t ( '%%.%d f ' % p e
a h a n , nilai , True )
7
8
9 if __name__ == '__main__ ' :
10 print uang ( 1 0 0 0 0 )
11 print uang ( 1 0 0 0 0 . 3 )
12 print uang ( 1 0 0 0 0 . 5 , 0 )
Cobalah.
1 $ python uang . py
2 10.000 ,00
3 10.000 ,30
4 10.000
Perhatikan bagian
'%%.%df' % pe
ahan
BAB 6. FUNGSI 39
2. Selain kondisi di atas maka nilai uang ditampilkan seperti biasa sesuai
jumlah pe
ahan yang disebutkan.
Masih di uang.py.
1 import lo
ale
2 l o
a l e . s e t l o
a l e ( l o
a l e . LC_ALL, ' id_ID . UTF−8 ' )
3
4
5 def uang ( n i l a i , p e
a h a n=None ) :
6 if pe
ahan is None :
7 if t y p e ( n i l a i ) == t y p e ( 0 ) :
8 pe
ahan = 0
9 else :
10 pe
ahan = 2
11 return l o
a l e . f o r m a t ( '%%.%d f ' % p e
a h a n , nilai , True )
12
13
14 if __name__ == '__main__ ' :
15 print uang ( 1 0 0 0 0 )
16 print uang ( 1 0 0 0 0 . 3 )
17 print uang ( 1 0 0 0 0 . 5 , 4 )
Jalankan lagi.
$ python uang.py
10.000
10.000,30
10.000,5000
Cermatilah baik-baik hasilnya. Di sini kita sudah mengenal fungsi yang memiliki
dua masukan dan juga memiliki nilai default pada salah satu masukannya. Juga
ada objek hampa bawaan Python bernama None.
Rasanya fungsi uang kurang lengkap bila tidak disertai dengan mata uangnya.
Kita akan jalankan skenario berikut ini:
1. Fungsi uang diberi satu masukan baru yaitu variabel tanda untuk memberi
kesempatan programmer memasukkan mata uang seperti Rp, $, dst.
BAB 6. FUNGSI 40
2. Bila variabel tanda tidak diisi maka mata uang diambil dari sistem, meng-
gunakan module lo
ale.
1 import lo
ale
2 l o
a l e . s e t l o
a l e ( l o
a l e . LC_ALL, ' id_ID . UTF−8 ' )
3 from types import IntType
4
5
6 def ribu ( n i l a i , p e
a h a n=None ) :
7 if pe
ahan is None :
8 if t y p e ( n i l a i ) == I n t T y p e :
9 pe
ahan = 0
10 else :
11 pe
ahan = 2
12 return l o
a l e . f o r m a t ( '%%.%d f ' % p e
a h a n , nilai , True )
13
14 def uang ( n i l a i , p e
a h a n=None , t a n d a=None ) :
15 if tanda is None :
16 tanda = l o
a l e . l o
a l e
o n v ( ) [ '
urren
y_symbol ' ℄
17 return '%s%s ' % ( t a n d a , ribu ( n i l a i , pe
ahan ) )
18
19
20 if __name__ == '__main__ ' :
21 print ribu (10000)
22 print ribu (10000.3)
23 print ribu (10000.5 , 4)
24 print uang ( 1 0 0 0 0 . 7 )
25 print uang ( 1 0 0 0 0 . 7 , 2, '$ ' )
26 print uang ( 1 0 0 0 0 . 7 , t a n d a= ' $ ' )
Perhatikan fungsi tambahan ribu(). Fungsi ini sebenarnya salinan dari fungsi
uang() sebelumnya. Mengapa tidak langsung mengubah fungsi uang() seperti
biasanya ?
Tujuannya adalah kita tidak ingin mengganggu algoritma yang sudah ber-
jalan baik itu. Sehingga bila ada kekeliruan pada algoritma di uang(), area
pen
arian kesalahan bisa diminimalisir.
Perhatikan juga baris terakhir,
Karena modul uang ini merupakan modul umum yang bisa digunakan oleh
banyak aplikasi, maka letakkanlah uang.py di /usr/lo
al/lib/python2.6/dist-
pa
kages agar bisa digunakan oleh program lainnya. Lalu uji keberadaannya di
modus interaktif.
Database
Database atau penyimpan data biasa digunakan untuk aplikasi bisnis seperti
kasir (point of sales), a
ounting, payroll, dsb.
Pasanglah
1 $ sudo su
Masukkan password user yang Anda gunakan ketika login pertama kali. Kini
Anda telah menjadi root, dan mulailah sebagai user postgres:
1 # su − postgres
Kini Anda sudah menjadi user postgres. Menurut ketentuan default, bila
user Linux dan user PostgreSQL sama maka tidak perlu password untuk login
ke PostgreSQL server. Sekarang mulailah membuat user database:
1 $
reateuser −P ilham
2 Enter password for new role :
3 Enter it again :
4 Shall the new role be a superuser? ( y /n ) n
5 Shall the new role be allowed to
reate databases? ( y/n )
n
6 Shall the new role be allowed to
reate more new roles? (
y /n ) n
Isilah password dengan 1234. Saat diketik password tidak akan ditampilkan.
Selebihnya user ilham ini tidak dizinkan sebagai superuser, tidak diizinkan mem-
buat database, dan tidak diizinkan membuat user.
Untuk menghapusnya:
1 $ dropuser ilham
42
BAB 7. DATABASE 43
Ini artinya kita membuat database bernama totalindo yang dimiliki oleh user
ilham. Untuk menghapusnya:
1 $ dropdb totalindo
1 $ psql
2 psql (8.4.4)
3 Type " help " for help .
4
5 p o s t g r e s=# \ l
6 List of databases
7 Name | Owner | En
oding | Collation |
8 −−−−−−−−−−−+−−−−−−−−−−+−−−−−−−−−−+−−−−−−−−−−−−−+
9 postgres | p o s t g r e s | UTF8 | id_ID . UTF−8 |
10 t e m p l a t e 0 | p o s t g r e s | UTF8 | id_ID . UTF−8 |
11 t e m p l a t e 1 | p o s t g r e s | UTF8 | id_ID . UTF−8 |
12 t o t a l i n d o | ilham | UTF8 | id_ID . UTF−8 |
13 (4 rows )
14
15 p o s t g r e s=#
1 p o s t g r e s=# \ q
2 $ whoami
3 postgres
Anda masih sebagai user postgres, keluarlah dengan perintah logout atau
tekan Ctrl-D:
1 $ logout
2 # whoami
3 root
Kini Anda sebagai root, keluarlah lagi dengan perintah logout agar kembali
sebagai user biasa:
1 # logout
2 $ whoami
3 sugiana
7.1 Tabel
1. Harus memiliki PRIMARY KEY, yaitu sebuah / beberapa eld yang men-
jadi identitas re
ord.
2. Sebisa mungkin setiap eld memiliki DEFAULT value dimana kalau tidak
diisi maka nilai default digunakan.
3. Sebisa mungkin setiap eld NOT NULL yang berarti harus diisi.
Perhatikan prompt
totalindo=>
totalindo(>
BAB 7. DATABASE 45
CREATE TABLE
menjadi
reate table
Sekarang kita lihat daftar tabel yang ada di database totalindo ini menggunakan
perintah \dt.
1 t o t a l i n d o=> \ d t
2 List of relations
3 S
hema | Name | Type | Owner
4 −−−−−−−−+−−−−−−−−−+−−−−−−−+−−−−−−−
5 publi
| pegawai | table | ilham
6 (1 row )
7
8 t o t a l i n d o=>
1 t o t a l i n d o=> \d pegawai
2 Table " p u b l i
. pegawai "
3 Column | Type |
Modifiers
4 −−−−−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−+−−−−−−−−−−−−−−−−−−−
5 id | integer | not null default
n e x t v a l ( ' pegawai_id_seq ' : : r e g
l a s s )
6 nama |
hara
ter varying (30) | not null
7 tgl_lahir | date | not null
8 Indexes :
9 " p e g a w a i _ p k ey" PRIMARY KEY, btree ( id )
10
11 t o t a l i n d o=>
BAB 7. DATABASE 46
7.1.1 Sequen
e
Sequen
e mirip tabel, tepatnya tabel satu re
ord yang berisi data untuk ke-
butuhan nomor urut. Pada
ontoh di atas sequen
e bernama pegawai_id_seq
otomatis terbentuk saat eld id pada tabel pegawai didenisikan sebagai seri-
al. Data pada sequen
e bisa dilihat sebagaimana tabel menggunakan perintah
SELECT.
Perhatikan perintah di baris pertama tidak diakhiri dengan titik koma yang
berarti perintah belum berakhir dan dilanjutkan di baris berikutnya. Perhatikan
juga prompt pada baris kedua menjadi
totalindo->
yakni menggunakan karakter minus ( - ) yang berarti baris ini merupakan ke-
lanjutan dari baris sebelumnya. Jika Anda salah dalam menuliskan perintah di
baris pertama dan terlanjur menekan Enter, akhiri saja dengan titik koma di
baris kedua. Kemudian mulai lagi dari awal. Berikut ini
ontoh kesalahan yang
bisa saja terjadi.
BAB 7. DATABASE 47
Perhatikan saat INSERT tadi eld id tidak disertakan, namun perintah SE-
LECT memperlihatkan bahwa eld id terisi dengan angka 1. Inilah yang dise-
but dengan eld autoin
rement. Lalu apa yang terjadi dengan sequen
e pe-
gawai_id_seq ?
Perhatikan kembali eld id yang terisi dengan angka 2, dan lihat juga pe-
gawai_id_seq.
Jika sudah tampak dmy seperti di atas maka Anda diizinkan mengisi eld tang-
gal dengan format tanggal-bulan-tahun. Namun jika Anda mendapati isinya
maka ubahlah mdy menjadi dmy, simpan, logout semua psql, dan restart Post-
greSQL.
Perlu Anda ketahui, format dmy otomatis Anda dapatkan bila saat instalasi
Ubuntu menggunakan bahasa Indonesia.
Cobalah untuk menambah data pegawai lagi dengan tanggal lahir berformat
tanggal-bulan-tahun.
Tampilkan pegawai yang lahir di tahun 1972 dan diurutkan mulai yang ter-
tua.
Gunakan DESC pada ORDER BY jika ingin diurut mulai yang termuda.
Tekan tombol panah atas untuk mengulang perintah sebelumnya dan tam-
bahkan DESC.
Manusia bisa jadi memahami mana nama laki-laki dan mana perempuan.
Namun komputer mengalami kesulitan bila mengandalkan nama. Oleh karena
itu kita perlu menambah eld pria yang bertipe logika (boolean). Kita membu-
tuhkan perintah ALTER TABLE di sini.
Seperti dijelaskan pada sesi Python sebelumnya, boolean hanya bisa diisi
dengan dua nilai, bisa True atau False. Kita menamakan eld ini dengan pria
dengan begitu nilai default-nya adalah True. Jika eld pria False berarti pegawai
tersebut perempuan. Sekarang kita lihat isi tabel pegawai setelah penambahan
eld di atas.
Perhatikan eld pria, tampak semua tertulis t yang artinya True. Apa data
tabel ini sudah benar? Jelas belum.
Nita Pandria adalah perempuan, sedangkan tabel pegawai menyatakannya
laki-laki. Kita perlu mengubahnya dengan perintah UPDATE.
Jika Anda kurang suka dengan eld pria yang bertipe boolean bisa dihapus
dengan perintah ALTER TABLE.
SELECT, INSERT, UPDATE, dan DELETE adalah hal yang terkait den-
gan re
ord / baris data sehingga disebut sebagai Data Manipulation Language
(DML). Sedangkan CREATE, ALTER, dan DROP terkait dengan struktur tabel
sehingga disebut sebagai Data Denition Language (DDL).
7.2 View
Kolom ketiga berisi usia, tapi PostgreSQL tidak tahu harus dinamakan apa,
sehingga jadilah bernama ?
olumn?. Ada baiknya kita berikan nama usia.
Satuan usia menggunakan hari tentu saja kurang nyaman diba
a. Sebaiknya
kita ganti rumusnya:
Penamaan VIEW tidak harus berawalan v_. Penggunaan awalan itu un-
tuk membedakan VIEW dengan tabel sebenarnya. Meski ia dapat di-SELECT
namun VIEW tidak dapat di-INSERT begitu saja.
Walau v_pegawai sudah mengandung ORDER BY, kita masih bisa meng-
gunakan ORDER BY saat SELECT, misalnya diurut berdasar nama.
3 −−−−+−−−−−−−−−−−−−−−−−−+−−−−−−
4 2 | Arief Setiadi | 38
5 1 | Bummi Dwi Putera | 25
6 3 | Ce
ep Zahrudin | 38
7 4 | Nita Pandria | 34
8 (4 rows )
1 t o t a l i n d o=> \ i pegawai . s q l
2 p s q l : s q l / pegawai . s q l : 7 : NOTICE : CREATE TABLE will
reate
impli
it sequen
e " pegawai_id_seq " for serial
olumn
" pegawai . i d "
3 p s q l : s q l / pegawai . s q l : 7 : NOTICE : CREATE TABLE / PRIMARY
KEY w i l l
reate impli
it index " p e g a w a i _ p ke y" for
table " pegawai "
4 CREATE TABLE
5 INSERT 0 1
6 INSERT 0 1
7 INSERT 0 1
8 INSERT 0 1
1 t o t a l i n d o=> \ i /home/ s u g i a n a / p e g a w a i . s q l
Mulailah untuk latihan restore, yaitu dengan membuat database lain berna-
ma totalindo_1 (lihat pembuatan database di awal bab ini). Lalu jalankan:
7.3.1 En
oding
PostgreSQL versi terdahulu biasanya menggunakan SQL_ASCII sebagai en
od-
ing
hara
ter. Anda bisa lihat dengan perintah \l di psql.
Perhatikan di versi ini default en
oding adalah UTF8. Jika Anda memba
k-
up, perhatikanlah en
oding ini. Misalkan menggunakan SQL_ASCII, maka di
database yang baru pun Anda sebaiknya tetap menggunakan en
oding yang
sama. Sebagai latihan kembalilah ke konsole, lalu buat database totalindo_2
dengan en
oding SQL_ASCII.
1 $ sudo su
2 # su − postgres
3 $
reatedb −O ilham −T template0 −E sql_as
ii totalindo_2
Kembali ke psql dan lihat daftar database. Karena masih sebagai user post-
gres maka
ukup ketik psql.
1 $ psql
2 psql (8.4.4)
3 Type " help " for help .
4
5 p o s t g r e s=# \ l
6 List of databases
7 Name | Owner | En
oding | Collation |
8 −−−−−−−−−−−−−+−−−−−−−−−−+−−−−−−−−−−−+−−−−−−−−−−−−−+
9 postgres | p o s t g r e s | UTF8 | id_ID . UTF−8 |
10 template0 | p o s t g r e s | UTF8 | id_ID . UTF−8 |
11 template1 | p o s t g r e s | UTF8 | id_ID . UTF−8 |
12 totalindo | ilham | UTF8 | id_ID . UTF−8 |
13 totalindo_1 | ilham | UTF8 | id_ID . UTF−8 |
14 totalindo_2 | ilham | SQL_ASCII | id_ID . UTF−8 |
15 (6 rows )
7.4 Fungsi
Sama seperti Python, PostgreSQL juga mengenal fungsi. Contoh fungsi bawaan
(built-in) adalah now().
Keunikan fungsi pada PostgreSQL adalah pada nama dan susunan masukan-
nya (input parameter). Perhatikan
ontoh rata kanan berikut ini.
BAB 7. DATABASE 56
Fungsi lpad() berguna untuk memberi spasi di sebelah kiri. Jumlah spasi
ditambah jumlah karakter string 'A' tidak boleh melebihi 5. Jadi pada
ontoh
di atas jumlah spasi di sebelah kiri 'A' sebanyak 4 buah. Untuk membuktikan
jumlah karakternya adalah 5 maka kita gunakan fungsi length().
Sekarang kita membutuhkan awalan '0' pada sebuah nomor, misalnya '00001'.
Ini lazim kita temui pada beberapa laporan. Fungsi apa yang akan digunakan.
Jawabannya masih menggunakan fungsi lpad().
1. Jumlah masukannya.
2. Jika jumlah masukannya sama maka bedakan tipe data setiap masukan
tersebut.
7.4.1 PL/pgSQL
Salah satu yang membuat PostgreSQL begitu mudah dikembangkan adalah
fungsi tersebut bisa ditulis dalam berbagai bahasa. Dimana Anda bisa menulis
fungsi dalam bahasa pgSQL, Python, Perl, hingga T
l. Se
ara default bahasa
yang didukungnya adalah plpgsql. Namun Anda perlu memasangnya terlebih
dahulu pada database yang dimaksud.
sedangkan yang kedua untuk text editor vi. Tentu saja Anda bisa menggu-
nakan gedit. Text editor akan kita gunakan untuk membuat le-le *.sql.
Sekarang kita akan membuat fungsi sederhana hello(), tanpa masukan apapun,
disimpan dalam le hello.sql.
lalu obalah
Transaksi Perbankan
Kita sudah punya tabel pegawai dimana setiap pegawai dianggap sebagai nasabah
pada perusahaan ini. Saat mendapat gaji saldonya bertambah. Saat ambil gaji
saldonya berkurang. Saat kas bon (pinjam) saldonya juga berkurang. Jadi saldo
juga bisa negatif yang berarti pegawai tersebut punya hutang ke perusahaan.
Pertama kita butuh eld saldo pada tabel pegawai.
Kemudian untuk men
atat aktivitas transaksi kita memerlukan tabel transak-
si berikut ini.
Ya, kita butuh dua query untuk sebuah transaksi. Mungkin ada pertanyaan,
untuk apa eld saldo pada tabel transaksi ? Field ini digunakan untuk memu-
dahkan pen
etakan buku tabungan yang biasanya men
antumkan saldo pada
setiap transaksi.
Kalau diperhatikan, transaksi tersebut membutuhkan 3 parameter masukan:
1. ID pegawai
2. Keterangan transaksi
3. Nominal transaksi
Kalau transaksi ini dikemas dalam sebuah fungsi, lalu apa keluarannya ? Kelu-
aran atau output yang paling tepat adalah ID transaksi. Query-nya bisa kita
peroleh dengan
ara berikut ini.
1 id | pid | tgl |
2 −−−−+−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−+
3 1 | 1 | 2010 − 10 − 22 1 7 : 5 8 : 0 1 . 8 6 |
4
5 ket | nominal | saldo
6 −−−−−−−−−−−−−−+−−−−−−−−−+−−−−−−−−−
7 GAJI 11 − 2010 | 3 0 0 0 0 0 0 | 3 0 0 0 0 0 0
6 LANGUAGE p l p g s q l
7 AS $$
8 DECLARE
9 re
re
ord ;
10 BEGIN
11 UPDATE pegawai
12 SET s a l d o = s a l d o + p_nominal
13 WHERE i d = p_pid ;
14
15 INSERT INTO transaksi (
16 id , pid , nominal , ket , saldo )
17 SELECT tid , p_pid , p_nominal , p_ket , saldo
18 FROM pegawai
19 WHERE i d = p_pid ;
20
21 SELECT id
22 INTO re
23 FROM transaksi
24 ORDER BY DESC id
25 LIMIT 1;
26
27 RETURN r e
. i d ;
28 END
29 $$
Perhatikan nominal berisi nilai negatif yang artinya mengurangi saldo. Sekarang
lihat keseluruhan transaksi.
Dilihat dari aspek ke
epatan, query SELECT terhadap tabel transaksi bisa
dihindari. Maklumlah tabel transaksi ini tergolong
epat pertumbuhan re
ord-
nya. Jadi untuk mendapatkan ID transaksi kita perlu menggunakan sequen
e
yang dimiliki tabel transaksi tersebut. Ubahlah fun
transaksi.sql menjadi berikut
ini.
Restore.
7.4.2 PL/Python
Penulisan fungsi PostgreSQL bisa juga dalam bahasa Python. Biasanya saya
gunakan bahasa ini untuk algoritma yang tidak membutuhkan akses database.
Pasanglah terlebih dahulu.
Lalu obalah.
Sampai di sini Python sudah terhubung ke PostgreSQL dan uji
oba login
berhasil dengan perintah
onne
t(). Anda bisa lanjutkan dengan perintah query
untuk melihat re
ord tabel pegawai.
Lalu bagaimana kalau kita ingin melihat nilai berdasarkan nama eld-nya
? Untunglah variabel r di atas bisa dianggap sebagai di
tionary yang keys-nya
berisi nama eld dari query bersangkutan.
63
BAB 8. PYTHON AKSES DATABASE 64
1 >>> q = db . e x e
u t e ( s q l )
2 >>> f o r r in q:
3 ... print r [ ' id ' ℄ , r [ ' nama ' ℄
4 ...
5 1 Bummi Dwi Putera
6 2 Arief Setiadi
7 3 Ce
ep Zahrudin
8 4 Nita Pandria
1 >>> q = db . e x e
u t e ( s q l )
2 >>> f o r r in q:
3 ... print r . id , r . nama
4 ...
5 1 Bummi Dwi Putera
6 2 Arief Setiadi
7 3 Ce
ep Zahrudin
8 4 Nita Pandria
Mudah bukan ?
Fungsi exe
ute() bisa juga digunakan untuk perintah query lainnya seperti
INSERT, UPDATE, dan DELETE. Contohnya mengganti huruf pada eld nama
dengan kapital.
Anda memiliki data pegawai dalam sebuah le yang berformat CSV yang isinya
seperti ini:
4 4 ; NITA PANDRIA; 1 9 7 6 − 0 9 − 1 9 ; f
5 5 ; ILHAM; 1 9 8 4 − 1 1 − 0 5 ; t
File ini men
erminkan tabel pegawai dimana setiap eld dipisahkan dengan
titik koma ( ; ). Sedangkan identitas baris berupa ID pegawai yang berada di
kolom pertama, persis seperti tabel pegawai. Tugasnya adalah menyalin isi le
ini ke dalam tabel pegawai. Jika ID pegawai sudah ada maka lakukan UPDATE,
jika belum berarti INSERT.
Mari kita lihat terlebih dahulu isi tabel pegawai melalui psql.
Buatlah le pegawai.
sv terlebih dahulu dengan isi seperti di atas. Kemudian
buatlah le updatepegawai.py.
11 pid = i n t ( pid )
12 p r i a = p r i a == 't ' # Agar b o o l e a n True / F a l s e
13 sql = "SELECT * FROM p e g a w a i WHERE i d = %d " % p i d
14 q = db . e x e
u t e ( s q l )
15 if q . row
ount :
16 s q l = "UPDATE p e g a w a i SET " + \
17 "nama = '% s ' , " + \
18 " t g l _ l a h i r = '% s ' , " + \
19 " p r i a = %s " + \
20 "WHERE i d = %d "
21 s q l = s q l % ( nama , tgl_lahir , pria , pid )
22 else :
23 s q l = "INSERT INTO p e g a w a i " + \
24 " ( id , nama , tgl_lahir , pria ) " + \
25 "SELECT %d , '% s ' , '% s ' , %s "
26 s q l = s q l % ( pid , nama , tgl_lahir , pria )
27 db . e x e
u t e ( s q l )
Jalankan.
1 $ python u p d a t e p e g a w a i . py
Agar proses UPDATE dan INSERT masih terasa, buatlah perubahan pada
pegawai.
sv berikut ini.
4 4 ; NITA PANDRIA; 1 9 7 6 − 0 9 − 1 9 ; f
5 5 ; ILHAM; 1 9 8 4 − 1 1 − 0 5 ; t
6 6 ;MIRANDA; 1 9 7 8 − 1 0 − 0 1 ; f
Jalankanlah.
1 $ python u p d a t e p e g a w a i 1 . py
Hasil sudah sesuai harapan dengan sour
e yang jauh lebih mudah diba
a.
Pahamilah baik-baik mengenai konsep a
tive re
ord ini.
Lalu bagaimana menghapus salah satu re
ord ? Buatlah le deletepegawai.py
berikut ini.
1 $ python d e l e t e _ p e g a w a i . py 4
2 ID pegawai 4 sudah dihapus
Jalankan.
Butuh tampilan yang urut berdasarkan nama ? Kita biasa menggunakan OR-
DER BY pada query, disini bisa menggunakan order_by() sebagai pengganti
all().
3
4
lass Pegawai ( E n t i t y ) :
5 u s i n g _ o p t i o n s ( t a b l e n a m e= ' p e g a w a i ' , a u t o l o a d=True )
6
7 metadata . b i n d = ' p o s t g r e s : / / ilham :1234 lo
alhost /
totalindo '
8 setup_all ()
9
10 for r in P e g a w a i . q u e r y . o r d e r _ b y ( ' nama ' ) :
11 print r . id , r . nama , r . tgl_lahir , r . pria
Jalankan.
1 $ python s e l e
t _ p e g a w a i . py
2 2 ARIEF SETIADI 1972 − 05 − 02 True
3 1 BUMMI DWI PUTERA, ST 1985 − 08 − 17 True
4 3 CECEP ZAHRUDIN , ST 1972 − 06 − 01 True
5 5 ILHAM 1984 − 11 − 05 True
6 6 MIRANDA 1978 − 10 − 01 False
Jalankan.
1 $ python s e l e
t _ p e g a w a i . py
2 2 ARIEF SETIADI 1972 − 05 − 02 Pria
3 1 BUMMI DWI PUTERA, ST 1985 − 08 − 17 Pria
BAB 8. PYTHON AKSES DATABASE 71
1 $ dpkg −s python − e l i x i r
2 Pa
kage : python − e l i x i r
3 Version : 0.7.1 −1
4 Depends : p y t h o n (>= 2.4) , python −s u p p o r t (>= 0.90.0) ,
python − s q l a l
h e m y (>= 0.4.0)
5 Des
ription : De
larative Mapper for SQLAl
hemy
Masih ingat fungsi sql bernama transaksi() ? Kali ini akan kita buat transaksi
perbankan se
ara interaktif. Buatlah transaksi.py berikut.
23
24 n o m i n a l = r a w _ i n p u t ( ' Nominal : ')
25 try :
26 nominal = f l o a t ( nominal )
27 ex
ept ValueError :
28 s y s . e x i t ( ' Nominal %s tidak benar ' % nominal )
29
30 sql = "SELECT t r a n s a k s i (%d , ' % s ' , % . 2 f ) " % ( p i d , ket ,
nominal )
31 q = db . e x e
u t e ( s q l )
32 print ' Transaksi berhasil , ID ' , q . fet
hone () . transaksi
Jalankan.
1 $ python t r a n s a k s i . py
2 Transaksi
3 ID pegawai : 3
4 Nama : CECEP ZAHRUDIN , ST
5 Keterangan : GAJI 11 − 2010
6 Nominal : 4500000
7 Transaksi berhasil , ID 4
q = db.exe ute(sql)
menjadi
Pelanggan Anda memiliki usaha di bidang mini market dan telah memiliki be-
berapa outlet. Semua outlet itu telah terhubung ke Internet. Internet digunakan
BAB 8. PYTHON AKSES DATABASE 74
untuk mengambil data produk yang dikirim kantor pusat melalui email. Data
produk tersebut tersimpan dalam atta
hment. User di outlet menyimpannya ke
folder tertentu untuk selanjutnya dimasukkan ke database outlet melalui menu
Restore yang telah disediakan di aplikasi. Begitu juga dengan data transak-
si. Data disimpan terlebih dahulu ke dalam sebuah le melalui menu Ba
kup.
Selanjutnya le tersebut di-email ke kantor pusat.
Teknik ini sudah baik, namun lebih baik lagi jika pekerjaan itu dilakukan
oleh s
ript yang disebut syn
hronizer.
Kita membi
arakan mekanisme otomatis penuh, dimana syn
hronizer dipi
u
oleh waktu, misalkan jam 9:00 dan jam 17:00 setiap harinya. Berbeda dengan
teknik sebelumnya, syn
hronizer tidak menggunakan email untuk komunikasi
data. Ia bekerja langsung dengan database pusat dan database outlet.
Lalu bagaimana kedua host outlet dan pusat saling terhubung ?
Ya, kita memerlukan IP publik di kantor pusat agar syn
hronizer di out-
let dapat mengakses database pusat. IP publik ini dapat dipesan ke ISP (In-
ternet Servi
e Provider) bersangkutan. Setelah IP publik didapat, tambahkan
baris berikut ini di /et
/postgresql/8.4/main/pg_hba.
onf:
Kongurasi ini artinya semua host dapat mengakses database pusat, tentunya
dengan otentikasi username dan password. Simpan dan restart daemon-nya:
url = 'postgresql://ilham:1234110.137.120.251/totalindo'
Mudah bukan ?
di outlet. Dengan VPN ini terbentuk jaringan baru dengan IP pusat 10.8.0.1,
sedangkan IP outlet 10.8.0.6, 10.8.0.10, 10.8.0.14, dst. Baik VPN server maupun
VPN
lient bisa kita gunakan OpenVPN. Untuk pemasangan keduanya silahkan
ba
a url berikut ini:
http://jabber.rab. o.id/os/konfigurasi-openvpn
1 $ if
onfig tun0
2 tun0 Link e n
a p : UNSPEC HWaddr
00−00−00−00−00−00−00−00−00−00−00−00−00−00−00−00
3 inet addr : 1 0 . 8 . 0 . 6 P−t −P : 1 0 . 8 . 0 . 5 Mask
:255.255.255.255
4 UP POINTOPOINT RUNNING NOARP MULTICAST MTU
:1500 Metri
: 1
5 RX p a
k e t s : 0 errors :0 dropped : 0 overruns :0
frame : 0
6 TX p a
k e t s : 6 errors :0 dropped : 0 overruns :0
arrier :0
7
o l li s i on s :0 txqueuelen :100
8 RX b y t e s : 0 (0.0 B) TX b y t e s : 9 6 3 ( 9 6 3 . 0 B)
Anda sudah memiliki aplikasi yang menggunakan MySQL, dan kini ingin beralih
ke PostgreSQL. Setidaknya dibutuhan penyalinan struktur tabel beserta isinya.
Terlebih dahulu pasanglah driver MySQL.
Database Paket
Contoh penggunaan:
1 python d b m i g r a t i o n . py m y s q l : / / r o o t : 6 7 8 9 l o
a l h o s t / sumber
postgres :// j e f r i :1234 lo
alhost / target
1 $ dpkg −s python − s q l a l
h e m y
2 ..
3 Suggests : python −s q l a l
h e m y −do
, python −p s y
o p g 2 , python −
mysqldb (>= 1 . 2 . 1 − p2 − 2) , p y t h o n (>= 2.5) | python −
pysqlite2 (>= 2 . 3 . 0 − 1 ) | python − p y s q l i t e 1 . 1 (>=
1.1.7 −2) | python − s q l i t e (>= 1 . 0 . 1 − 5 ) , python −
kinterbasdb (>= 3.1.2 −0.3) , python −p y m s s q l
4 ..
Lintas Sistem
Kita telah membahas mengenai manfaat modularitas dalam fungsi dan modul
dimana sebuah aplikasi disusun bagaikan sebuah lego. Jika keseluruhan sistem
semakin kompleks maka hindari konsep pemaksaan seperti semua harus dit-
ulis dengan Python atau semua harus menggunakan PostgreSQL. Kali ini kita
oba pahami bagaimana komunikasi antar sistem bisa terjadi tanpa pemaksaan
platform tertentu.
1 $ if
onfig
2 eth0 Link en
ap : Ethernet HWaddr 0 0 : 2 5 : b3 : 7 7 : 3 e : 9 9
3 inet addr : 1 9 2 . 1 6 8 . 1 1 . 1 1 1 B
ast : 1 9 2 . 1 6 8 . 1 1 . 2 5 5
Mask : 2 5 5 . 2 5 5 . 2 5 5 . 0
4 UP BROADCAST MULTICAST MTU: 1 5 0 0 Metri
: 1
5 RX p a
k e t s : 0 errors :0 dropped : 0 overruns :0
frame : 0
6 TX p a
k e t s : 0 errors :0 dropped : 0 overruns :0
arrier :0
7
o l li s i on s :0 txqueuelen :1000
8 RX b y t e s : 0 (0.0 B) TX b y t e s : 0 (0.0 B)
9 Interrupt :17
10
11 lo Link en
ap : Lo
al Loopba
k
12 inet addr : 1 2 7 . 0 . 0 . 1 Mask : 2 5 5 . 0 . 0 . 0
13 inet6 addr : ::1/128 S
ope : Host
14 UP LOOPBACK RUNNING MTU: 1 6 4 3 6 Metri
: 1
80
BAB 9. LINTAS SISTEM 81
1 import
ommands
2 import re
3
4 def netdev ( ) :
5 r = {}
6 for line in
ommands . g e t o u t p u t ( ' i f
o n f i g ' ) . s p l i t l i n e s
() :
7 line = line . strip ()
8 mat
h = r e .
o m p i l e ( ' ( . * ) L i n k en
ap ( . * ) ' ) . s e a r
h (
line )
9 if mat
h :
10 d e v i
e = mat
h . g r o u p ( 1 ) . s t r i p ( )
11 r [ devi
e ℄ = {}
12 mat
h = r e .
o m p i l e ( ' HWaddr ( . * ) ' ) . sear
h ( l i n e
)
13 if mat
h :
14 r [ d e v i
e ℄ [ ' addr ' ℄ = mat
h . g r o u p ( 1 )
15
ontinue
16 mat
h = r e .
o m p i l e ( ' i n e t addr : ( . * ) ' ) . s e a r
h ( l i n e )
BAB 9. LINTAS SISTEM 82
17 if mat
h :
18 r [ devi
e ℄ [ ' ip ' ℄ = mat
h . g r o u p ( 1 ) . s p l i t ( ) [ 0 ℄
19 return r
20
21
22 if __name__ == '__main__ ' :
23 nd = n e t d e v ( )
24 for dev in nd :
25 print dev , nd [ d e v ℄
Jalankan.
1 $ python n e t d e v . py
2 wlan0 { ' ip ' : '192.168.1.4 ' , ' addr ' : ' 0 0 : 1 f : 3
: e0 : 6 6 : 5 6 ' }
3 lo { ' ip ' : '127.0.0.1 '}
4 eth0 { ' ip ' : '192.168.11.111 ' , ' addr ' : ' 0 0 : 2 5 : b3 : 7 7 : 3 e
:99 '}
Lintas sistem yang menggunakan
ommand line ini tergolong lokal, artinya
netdev.py harus berada di komputer yang sama dengan if
ong.
9.2 File
File bisa digunakan sebagai sarana pemersatu input dan output. Misalkan An-
da sudah membuat sebuah daemon yang dapat menerima dan mengirim SMS.
Daemon ini pengendali modem. Oh ya, daemon adalah program yang selalu
hidup untuk siap menerima perintah.
Di sisi lain Anda juga punya program penerjemah SMS yang masuk (SMS
parser) dan juga berfungsi untuk membalas ke si pengirim. Bagaimana kedua
program ini dapat berhubungan ?
Anda bisa menggunakan le sebagai perantara. Saat ada SMS masuk, dae-
mon pengendali modem menyimpannya dalam sebuah le di direktori /var/spool/-
modem/inbox. Kemudian SMS parser memba
a direktori ini, menerjemahkan
lenya, dan membalas SMS tersebut dengan
ara membuat le di direktori
/var/spool/modem/outbox. File tersebut diba
a oleh daemon si modem untuk
kemudian mengirim SMS yang dimaksud.
Baik daemon modem maupun SMS parser bisa ditulis dengan bahasa yang
berbeda. Mungkin yang pertama dengan C++, sementara yang satunya di tulis
dengan Python. Namun keduanya bekerja menggunakan direktori yang sama.
Ini juga tergolong lintas sistem yang lokal, keduanya harus di komputer yang
sama.
Dengan teknik NFS atau Samba Anda bisa membuat direktori bersama
(sharing dire
tory) di komputer lain (remote host).
BAB 9. LINTAS SISTEM 83
9.3 Database
Pelanggan Anda telah memiliki sebuah sistem pengisian pulsa dimana terdapat
fungsi yang berkaitan dengan GSM modem. Fungsi yang dimaksud adalah yang
berkaitan dengan SMS gateway yaitu mengirim dan menerima SMS.
Pelanggan ini telah membuat sistemnya menggunakan Borland Delphi (ba-
hasa Pas
al) dan menggunakan database MySQL. Ia mengeluh pada Anda se-
laku developer outsour
ing dimana komponen SMS gateway yang dibangun-
nya tidak stabil. Di sisi lain Anda telah membuat SMS gateway yang ditulis
dengan bahasa Python dan database PostgreSQL. Tidak seperti yang dimiliki
pelanggan tersebut, SMS gateway yang Anda buat sangat stabil dan telah teruji
bertahun-tahun. Masalah penyatuan semakin bertambah dimana SMS gateway
Anda berada di sistem operasi Linux, sementara pelanggan Anda menggunakan
Mi
rosoft Windows.
Langkah apa yang diambil untuk membuat SMS gateway-nya stabil ? An-
da belajar Borland Delphi untuk menerjemahkan algoritma Python ? Atau
memaksa pelanggan Anda itu untuk belajar Python dan membangun ulang
sistem pengisian pulsanya ?
Langkah yang bijaksana tentu tidak keduanya, karena porsi tidak seimbang
yang mengakibatkan penyatuan menjadi sangat lama. Solusi sederhana adalah
menggunakan database sebagai perantara. Mintalah padanya untuk menyedi-
akan sebuah komputer lagi untuk SMS gateway Anda, sebut saja server SMS
gateway. Server ini terhubung melalui LAN (lo
al area network) dengan server
pengisian pulsa yang berbasis Windows tadi.
Tanpa perubahan ? Tentu saja ada.
Ran
angan SMS gateway yang Anda buat harus dapat mengirim SMS hanya
dengan menggunakan perintah INSERT. Contoh:
Lalu apa yang dilakukan oleh pelanggan Anda tadi ? Ia perlu mengubah
sour
e Borland Delphi-nya, yaitu pada fungsi pengiriman SMS menggunakan
koneksi ke database PostgreSQL yang ada di server SMS gateway. Biasanya
driver ODBC dapat mengatasi hal ini.
Lho, bukankah ia menggunakan MySQL sebagai database ? Benar, MySQL
untuk komponen pengisian pulsa tetap berlaku. Jadi dalam aplikasi Borland
Delphi terdapat dua koneksi database, yaitu ke MySQL yang ada di lo
alhost
Mi
rosoft Windows, dan ke PostgreSQL yang ada di remote host Linux.
Lalu bagaimana untuk memba
a SMS yang masuk ? Kembali, Anda diminta
untuk menyimpan SMS yang masuk ke dalam sebuah tabel, katakanlah bernama
inbox. Selanjutnya pelanggan Anda dapat memba
anya menggunakan perintah
SELECT pada Borland Delphi.
Mudah bukan ? Lebih lanjut mengenai SMS gateway bisa lihat halaman115.
BAB 9. LINTAS SISTEM 84
Lintas sistem ini tergolong bisa beda komputer, karena baik PostgreSQL
maupun MySQL dapat diakses melalui jalur network.
9.4 XMLRPC
Database sebagai perantara bisa jadi ditolak dengan berbagai alasan. Salah
satunya adalah aspek tanggung jawab, atau biasa disebut aspek keamanan (se-
urity). Misalkan dalam sistem perbankan. Sistem utama sebuah bank diban-
gun oleh PT Software Aman Banget (SAB). Namanya juga sistem utama, ia
memuat data penting nasabah serta data yang menyangkut sistem.
Suatu saat bank ini ingin go Internet dimana nasabah dapat melakukan
transaksi melalui browser Firefox. Berarti dibutuhkan web developer dan dip-
ilihlah PT Web Perkasa (WP) untuk mengembangkannya. Karena mengem-
bangkan Internet banking, berarti ada proses login untuk nasabah. Ini berarti
ada algoritma pemeriksaan username dan password. Sampai disini tidaklah
menjadi masalah karena username dan password web bisa berada di web server
yang dibangun oleh WP.
Tibalah saatnya nasabah ingin melihat mutasi transaksinya. Apakah WP
melakukan SELECT tabel ke sistem utama bank tersebut yang dibangun oleh
SAB ?
Mayoritas jawabannya tidak. Mengapa ?
SELECT berarti kita bi
ara koneksi ke database. Itu artinya WP menge-
tahui username dan password untuk login ke database sistem utama. Kalau
sudah begitu maka WP bisa melihat-lihat data nasabah lainnya, bahkan meli-
hat tabel-tabel yang menyangkut sistem. Jelas ini sudah terlalu jauh dan bisa
menimbulkan hal-hal yang tak perlu.
Untuk menghindari koneksi database ke sistem utama, maka digunakanlah
XMLRPC sebagai perantaranya. Makanan apakah ini ?
XMLRPC adalah XML Remote Pro
edure Call, yaitu sebuah bahasa per-
tukaran data yang ditulis dalam format XML. Kita dapat memandang RPC
sebagai pemanggilan fungsi yang memiliki nilai masukan (input parameter) dan
nilai keluaran (output / return value). Sebagaimana fungsi sederhana ini.
1 def tambah ( a , b) :
2 return a + b
XMLRPC bisa juga disebut sebagai web servi
e karena dokumen XML
tersebut dikirim menggunakan HTTP atau HTTPS dengan method POST.
Karena web servi
e, maka kita bi
ara koneksi
lient - server, sehingga ada
penyebutan XMLRPC
lient dan XMLRPC server. Penggunaannya tergolong
simple dan pustakanya (library) banyak tersedia untuk berbagai bahasa seperti
Python, PHP, Java, Borland Delphi, Visual Basi
, dst.
Kembali pada web developer di atas. WP mengembangkan web-nya menggu-
nakan PHP, sementara SAB mengembangkan sistem bank menggunakan Python.
Database keduanya juga berbeda dimana WP menggunakan MySQL, sedangkan
SAB menggunakan PostgreSQL. Namun semuanya itu tidak lagi menjadi hal.
BAB 9. LINTAS SISTEM 85
38 r = r e s p ( 0 , 'OK ' )
39 r [ ' mutasi ' ℄ = m
40 return r
41
42
43
44 url = ' p o s t g r e s q l : / / ilham :1234 lo
alhost / t o t a l i n d o '
45 db = s a .
r e a t e _ e n g i n e ( u r l )
46
47 port = 9303
48 s e r v e r = Server ( ( ' 0 . 0 . 0 . 0 ' , port ) )
49 server . register_introspe
tion_fun
tions ()
50 s e r v e r . r e g i s t e r _ i n s t a n
e ( Agent ( ) )
51 print 'HTTP XMLRPC s e r v e r port ' , port
52 server . serve_forever ()
Jalankan.
1 $ python s e r v e r b a n k . py
2 HTTP XMLRPC s e r v e r port 9303
1 $ python
l i e n t b a n k . py
2 2010 − 10 − 22 GAJI 11 − 2010 3000000 3000000
3 2010 − 10 − 22 BON − 200000 2800000
BAB 9. LINTAS SISTEM 87
Cermati baik-baik konsepnya. Juga perhatikan tipe data di
tionary dan list
yang digunakan sebagai nilai keluaran (return value) dari fungsi mutasi.
1 <?php
2 in
lude ( ' xmlrp
. i n
' ) ;
3 $params = new xmlrp
val (
4 array (
5 ' p i d ' => new xmlrp
val (1 , ' int ' ) ,
6 ' a w a l ' => new xmlrp
val ( ' 20101022 ' ) ,
7 ' a k h i r ' => new xmlrp
val ( ' 20101023 ' )
8 ) ,
9 ' stru
t '
10 ) ;
11 $ f = new xmlrp
msg ( ' m u t a s i ' , array ( $params ) ) ;
12 $
= new xmlrp
_
lient( ' / ' , ' 127.0.0.1 ' , 9303) ;
13 $ r = $
−>s e n d ( $ f ) ;
14 $v = $ r −>v a l u e ( ) ;
15 if ( $ r −>f a u l t C o d e ( ) ) {
16 print − $r >f a u l t S t r i n g ( ) ;
17 } else {
18 $ r e s p = $ r >s
a l a r v a l ( ) ;
if
−
19 ( $ r e s p [ ' k o d e ' ℄−> s
a l a r v a l ( ) == 0 ) {
20 forea
h ( $ r e s p [ ' m u t a s i ' ℄−> s
a l a r v a l ( ) as $ i=>$m) {
21 $ f = $m−>s
a l a r v a l ( ) ;
22 $ t g l = $ f [0℄ − > s
a l a r v a l ( ) ;
23 $ k e t = $ f [0℄ − > s
a l a r v a l ( ) ;
24 $ n o m i n a l = $ f [0℄ − > s
a l a r v a l ( ) ;
25 $ s a l d o = $ f [0℄ − > s
a l a r v a l ( ) ;
26 print $tgl . " ".
27 str_pad ( $ket , 20) . " ".
28 str_pad ( $nominal , 10) . " ".
29 str_pad ( $saldo , 1 0 ) . " \n" ;
30 }
31 } else {
32 print $ r e s p [ ' p e s a n ' ℄−> s
a l a r v a l ( ) ;
33 }
34 }
35 ?>
BAB 9. LINTAS SISTEM 88
Karena s
ript ini akan kita jalankan sebagai
ommand line, maka pasang
dulu paket terkait.
Lalu jalankan.
1 $ php
l i e n t _ b a n k . php
2 2010 − 10 − 22 GAJI 11 − 2010 3000000 3000000
3 2010 − 10 − 22 BON − 200000 2800000
9.4.2 Drupal
Drupal
1 juga ditulis dengan PHP. Ia sudah memuat fun
tion xmlrp
, sehingga
Anda tidak perlu memasang modul tambahan. Cara penulisannya juga lebih
mudah. Contoh berikut ini untuk Drupal 6.
Buatlah le sites/all/modules/pegawai/pegawai.module berikut.
1 <?php
2 fun
tion pegawai_menu ( ) {
3 $items = array () ;
4 $ i t e m s [ ' p e g a w a i / t r x /%/%/% ' ℄ = array (
5 ' t i t l e ' => ' Transaksi ' ,
6 ' page
a l l b a
k ' => ' pegawai_trx ' ,
7 ' page a r g u m e n t s ' => array (2 , 3, 4) ,
8 ' a
ess
a l l b a
k ' => ' user_a
ess ' ,
9 ' t y p e ' => MENU_CALLBACK,
10 ) ;
11 return $items ;
12 }
13
14 fun
tion pegawai_trx ( $pid , $awal , $akhir ) {
15 $url = ' http : / / 1 2 7 . 0 . 0 . 1 : 9 3 0 3 ' ;
16 $p = array ( ' p i d ' => intval ( $pid ) ,
17 ' a w a l ' => $ a w a l ,
18 ' a k h i r ' => $ a k h i r ) ;
19 $r = xmlrp
( $url , ' mutasi ' , $p ) ;
20 if ( ! $r [ ' mutasi ' ℄ ) {
21 return drupal_set_message ( ' Tidak ada data ' ) ;
22 }
23 $
= '<t a b l e ><th>T a n g g a l </th><th>K e t e r a n g a n</th> ' .
24 '<th>Nominal</th><th>S a l d o </th ></t r > ' ;
25 forea
h ( $r [ ' mutasi ' ℄ as $ i=>$ f ) {
26 $tgl = $f [ 0 ℄ ;
1 http://drupal.org
BAB 9. LINTAS SISTEM 89
27 $ket = $f [ 1 ℄ ;
28 $nominal = $ f [ 2 ℄ ;
29 $saldo = $f [ 3 ℄ ;
30 $
.= '<t r ><td> ' . $ t g l . ' </td> ' ;
31 $
.= '<td> ' . $ k e t . ' </td> ' ;
32 $
.= '<t d a l i g n =" r i g h t "> ' . format_number ( $ n o m i n a l ) .
' </td> ' ;
33 $
.= '<t d a l i g n =" r i g h t "> ' . format_number ( $ s a l d o ) . '
</td> ' ;
34 $
.= ' </ t r > ' ;
35 }
36 return $
;
37 }
38 ?>
1 name = P e g a w a i
2 d e s
r i p t i o n = Data pegawai
3
ore = 6. x
4 v e r s i o n = " 6 . x −1.0"
pegawai/trx/1/20101022/20101023
Bab 10
Pengemasan
Pada bab sebelumnya kita sudah membuat modul uang.py. Agar modul ini dap-
at digunakan oleh user lainnya maka diletakkanlah di direktori /usr/lo
al/lib/python2.6/dist-
pa
kages. Proses
opy modul seperti ini memang sudah mudah, tapi ada lagi
yang lebih memudahkan, yaitu dengan mengemasnya dalam bentuk paket De-
bian.
Langkah kemudahan yang dimaksud adalah:
1. Tambahkan URL daftar paket dalam sebuah le /et
/apt/sour
es.list.d/
ustom.list
yang berisi
deb http://192.168.0.1/deb ./
90
BAB 10. PENGEMASAN 91
postinst s
ript yang dijalankan saat pemasangan berlangsung, yaitu saat apt-
get install atau dpkg -i. S
ript ini harus exe
utable yang bisa diset dengan
hmod 755.
prerm s
ript yang dijalankan saat penghapusan berlangsung, yaitu saat apt-
get remove atau dpkg -r. S
ript ini juga harus exe
utable.
onles berisi daftar nama le kongurasi yang digunakan paket ini. Misalnya
berisi /et
/uang.
onf. File kongurasi ini berisi format negara yang di-
gunakan oleh fungsi uang(). Jadi tidak hard-
ode menggunakan lo
ale
id_ID.UTF-8. Dengan begitu python-uang semakin umum (general).
Dengan didaftarkannya /et
/uang.
onf di dalam
onles, maka terhin-
dar dari penibanan (timpa / overwrite) saat upgrade berlangsung. Mis-
alkan kini python-uang versi 0.1. Kemudian dibuatlah versi 0.2 yang juga
memuat /et
/uang.
onf. Jika di dalam versi 0.2 tidak ada perubahan
apa-apa pada /et
/uang.
onf maka apt-get install tidak akan melakukan
timpa pada /et
/uang.
onf yang sudah terpasang . Karena siapa tahu
Anda sudah mengganti isi /et
/uang.
onf terpasang dengan de_DE.ISO-
8859-1. Dengan begitu kita terhindar dari mengubah ulang kongurasi.
Mudah-mudahan paham maksudnya.
1 $
d / usr/ l o
a l / sr
2 $ sudo mkdir −p python −uang / u s r / s h a r e / p y
e n t r a l / python −
uang / s i t e −p a
k a g e s
Perhatikanlah direktori setelah /usr/lo
al/sr
/python-uang. Semua direk-
tori tersebut nantinya akan dipasang di root dire
tory ( / ), ke
uali direktori
DEBIAN.
Lalu mengapa menggunakan /usr/share ? Padahal sebelumnya kita mele-
takkan uang.py di /usr/lo
al ? Direktori /usr/lo
al yang kita gunakan sebelum-
nya bermakna bahwa uang.py belum menjadi bagian dari paket Debian. Bila
sudah menjadi bagian dari paket Debian, maka diletakkan di /usr/share. Begi-
tulah ketentuan umumnya.
1 $ sudo
p / u s r / l o
a l / l i b / p y t h o n 2 . 6 / d i s t −p a
k a g e s / uang . py
python −uang / u s r / s h a r e / p y
e n t r a l / python −uang / s i t e −
pa
kages/
Karena akan menggunakan /et
/user.
onf, lakukan perubahan pada uang.py
menjadi berikut ini.
1 import lo
ale
2 from ConfigParser import ConfigParser
3
4
onf = ConfigParser ()
5
o n f . r e a d ( ' / e t
/ uang .
o n f ' )
6
7 l o
a l e . s e t l o
a l e ( l o
a l e . LC_ALL,
onf . get ( ' default ' , '
lo
ale '))
8
9 DECIMAL =
o n f . g e t i n t ( ' d e f a u l t ' , ' d e
i m a l ' )
10
11
12 def uang ( n i l a i , p e
a h a n=None ) :
13 if pe
ahan is None :
14 if t y p e ( n i l a i ) == t y p e ( 0 ) :
15 pe
ahan = 0
16 else :
17 p e
a h a n = DECIMAL
18 return l o
a l e . f o r m a t ( '%%.%d f ' % p e
a h a n , nilai , True )
19
20
21 if __name__ == '__main__ ' :
22 n = 10000.5
23 print uang ( n )
24 print uang ( i n t ( n ) )
25 print uang ( n , 3 )
BAB 10. PENGEMASAN 93
Buat direktori et .
1 [ default ℄
2 l o
a l e = id_ID . UTF−8
3 de
imal = 2
1 / e t / uang . o n f
1 #!/ b i n / s h
2 py
entral pkginstall python −uang
Juga python-uang/DEBIAN/prerm.
1 #!/ b i n / s h
2 py
entral pkgremove python −uang
Kemas.
Perhatikan ada titik diakhirnya yang berarti letakkan di
urrent dire
tory.
Abaikan saja peringatan itu. Karena Python-Version memang bukan standar
Debian, tapi digunakan oleh py
entral. Sampai di sini pembuatan paket selesai.
Kini telah terbentuk python-uang_0.1_all.deb yang siap dipasang.
Untuk menghindari keran
uan karena ada dua modul uang yang terpasang,
sebaiknya buang yang ada di /usr/lo
al.
1 $ s u d o mv / u s r / l o
a l / l i b / p y t h o n 2 . 6 / d i s t −p a
k a g e s / uang . py
/tmp
1 $ python
2 Python 2.6.5 ( r265 : 7 9 0 6 3 , Apr 16 2010 , 13:09:56)
3 [GCC 4 . 4 . 3 ℄ on linux2
4 Type " help " , "
opyright " , "
redits" or " li
ense " for more
information .
5 >>> f r o m uang import uang
6 >>> uang ( 1 0 0 0 0 )
7 '10.000 '
Kini saatnya membuat repository agar bisa di-apt-get dari komputer lain. Pasanglah
paket yang dibutuhkan untuk memba
a le-le *.deb.
Letakkan paketnya di tempat yang sudah ditentukan web server Apa he.
1 rm −f Pa
kages . gz
2 dpkg−s
a n p a
k a g e s −−a r
h all . >/d e v / n u l l > P a
k a g e s
3 gzip −− b e s t Pa
kages
1 $
d / v a r /www/ deb
2 $ sudo sh u p d a t e l i s t . sh
Akan terbentuk le Pa
kages.gz. File inilah yang akan diba
a saat apt-get
update.
Selanjutnya kita uji repository ini dengan membuat le /et
/apt/sour
es.list.d/
ustom.list.
1 deb h t t p : / / 1 9 2 . 1 6 8 . 0 . 1 / deb ./
1 $ sudo a p t −g e t update
BAB 10. PENGEMASAN 96
1 . ./
onf
2 mkdir −p /tmp /
drom /tmp / r o o t
3 mount −o l o o p $SOURCE /tmp /
drom
4 rsyn
−− e x
l u d e ' f i l e s y s t e m . s q u a s h f s ' −a /tmp /
drom /
drom /
5 mount −o loop −t squashfs /tmp /
drom /
a s p e r / f i l e s y s t e m .
squashfs /tmp / r o o t
6
p −a /tmp / r o o t .
7 umount /tmp / r o o t
8 umount /tmp /
drom
1
p / et
/ r e s o l v .
onf root / et
2
hroot root mount −t pro
none / pro
3
hroot root mount −t sysfs none /sys
4
hroot root
5 rm −f root / et
/ r e s o l v .
onf
6
hroot root a p t −g e t
lean
7
hroot root umount sys
8
hroot root umount pro
BAB 10. PENGEMASAN 97
1 . ./
onf
2 rm −f
drom /
a s p e r / f i l e s y s t e m . s q u a s h f s
3 awal=` date `
4 mksquashfs root
drom /
a s p e r / f i l e s y s t e m . s q u a s h f s
5
d
drom
6 find . − t y p e f − p r i n t 0 | x a r g s −0 md5sum > md5sum . t x t
7 mkisofs − r −V " $ {LABEL} " −
a
h e − i n o d e s −J − l −b i s o l i n u x /
i s o l i n u x . b i n −
i s o l i n u x / b o o t .
at
−no−emul−b o o t −b o o t −
l o a d − s i z e 4 −b o o t − i n f o − t a b l e −o . . / $TARGET .
8 e
ho " Awal $awal "
9 e
ho " Akhir " ` date `
10 e
ho " Sour
e " ` ls −l $SOURCE | awk '{ print $5 } ' `
11 e
ho " Target " ` ls −l . . / $TARGET | awk '{ print $5 } ' `
1 $ sudo s h 1− e x t r a t . s h
Dia akan mengekstrak le iso menjadi root dire
tory. Kemudian jalankan
s
ript kedua:
1 $ sudo s h 2− h r o o t . s h
S ript ini untuk masuk ke sistem Linux yang lain, yaitu root dire tory tadi.
1 r o o t l a p t o p :/#
1 r o o t l a p t o p :/#
d / e t
/ apt / s o u r
e s . l i s t . d
2 r o o t l a p t o p :/# wget http : / / debian . rab .
o . i d / rab . l i s t
3 r o o t l a p t o p :/# a p t −g e t update
4 r o o t l a p t o p :/# a p t −g e t install internet −s h a r i n g dh
p3−
server squid vim
Kalau sudah selesai keluarlah dari
hroot dengan menekan Ctrl-D atau ketik
exit:
BAB 10. PENGEMASAN 98
1 r o o t l a p t o p :/# exit
2 exit
3 sugianalaptop :~ $
Root dire
tory kini telah berisi aplikasi yang dibutuhkan. Saatnya membuat
iso dengan menjalankan s
ript ketiga.
1 $ s u d o 3− p a k . s h
Terakhir s
ript akan memberikan informasi ukuran iso yang dihasilkan berikut
iso aslinya.
Jika media yang Anda tuju nanti adalah CDROM, pastikan ukurannya
dibawah 700MB. Lebih mudahnya bandingkan dengan ukuran ISO aslinya. Pa-
da
ontoh di atas terlihat ukuran Target masih lebih besar dari Sour
e. Jika
masih terlalu besar jalankan lagi s
ript kedua untuk menghapus paket yang tak
perlu.
1 $ sudo s h 2− h r o o t . s h
1 $ sudo s h 3− p a k . s h
File ISO yang dihasilkan bisa Anda
oba terlebih dahulu di VirtualBox .
1
Anda juga bisa memasangnya di ashdisk menggunakan usb-
reator-gtk. Jika
sudah yakin barulah membakarnya (burn) ke CD-ROM.
1 virtualbox.org
Bab 11
Seperti biasa, mulailah dari yang sederhana, yaitu membuat aplikasi Hello
world dalam le hello.py.
1 import sys
2 from PyQt4 import Qt
3 from PyQt4 . QtGui import *
4
5
lass FormUtama ( QMainWindow) :
6 def __init__ ( s e l f ) :
7 QMainWindow . __init__ ( s e l f )
8 s e l f . setWindowTitle ( ' Hello world ' )
9
10
99
BAB 11. GRAPHICAL USER INTERFACE 100
11 app = Qt . Q A p p l i
a t i o n ( s y s . a r g v )
12 fm = FormUtama ( )
13 fm . show ( )
14 #app . exe
_ ( )
Butuh tampilan penuh ? Gantilah
fm.show()
menjadi
fm.showMaximized()
lass FormUtama(QMainWindow):
fm = FormUtama()
QMainWindow.__init__(self)
fm.show()
dimana kita tidak pernah mendenisikan fungsi show() di dalam
lass FormU-
tama. Kenyataannya variabel fm memiliki fungsi show(). Darimana ia berasal
? Seperti dijelaskan tadi, FormUtama mewarisi sifat QMainWindow, jadi fungsi
show() itu berasal darinya. Fungsi ini digunakan untuk menampilkan form.
Lalu apa itu form ? Kotak Hello world itulah yang disebut form seperti pada
gambar 11.1.
Sekarang lihat baris 11
dimana QAppli
ation dibutuhkan untuk loop. Loop yang dimaksud adalah baris
terakhir
app.exe _()
tanpa loop, alur langsung berakhir. Form bisa banyak, tapi QAppli
ation
ukup
satu saja.
Pahami lagi baik-baik konsep OOP ini agar semakin mudah untuk membuat
aplikasi yang lebih besar.
Mari kita buat form yang lebih lengkap. Form ini untuk memasukkan data
pegawai, terinspirasi dari tabel pegawai yang pernah kita buat. Namun disini
belum menggunakan database, semuanya tersimpan sementara saja.
BAB 11. GRAPHICAL USER INTERFACE 102
1 import sys
2 from PyQt4 import Qt
3 from PyQt4 . QtGui import *
4 from PyQt4 . QtCore import QDate , SIGNAL
5
6
lass FormUtama ( QMainWindow) :
7 def __init__ ( s e l f ) :
8 QMainWindow . __init__ ( s e l f )
9 s e l f . s e t W i n d o w T i t l e ( ' Pegawai ' )
10 s e l f . r e s i z e (550 ,550)
11 s e l f . l a b e l N a m a = QLabel ( s e l f )
12 s e l f . l a b e l A l a m a t = QLabel ( s e l f )
13 s e l f . l a b e l T g l L a h i r = QLabel ( s e l f )
14 sel f . labelJenis = QLabel ( s e l f )
15 s e l f . editNama = Q L i n e E d i t ( s e l f )
16 s e l f . e d i t A l a m a t = QTextEdit ( s e l f )
17 s e l f . e d i t T g l L a h i r = QDateEdit ( s e l f )
18 s e l f . e d i t J e n i s = QComboBox ( s e l f )
19 s e l f . b u t t o n S i m p a n = QPushButton ( s e l f )
20 s e l f . listPegawai = QTableWidget ( s e l f )
21 s e l f . l a b e l N a m a . s e t T e x t ( ' Nama ' )
22 s e l f . l a b e l A l a m a t . s e t T e x t ( ' Alamat ' )
23 s e l f . l a b e l T g l L a h i r . s e t T e x t ( ' Tgl Lahir ' )
24 s e l f . l a b e l J e n i s . setText ( ' Jenis Kelamin ' )
25 s e l f . e d i t T g l L a h i r . s e t D i s p l a y F o r m a t ( ' dd−MM−yyyy ' )
26 s e l f . e d i t T g l L a h i r . s e t D a t e ( QDate ( 2 0 1 0 , 1 0 , 2 3 ) )
27 s e l f . e d i t J e n i s . a d d I t e m s ( [ ' P r i a ' , ' Wanita ' ℄ )
28 s e l f . b u t t o n S i m p a n . s e t T e x t ( ' Simpan ' )
29 s e l f . l i s t P e g a w a i . setColumnCount ( 5 )
30 s e l f . listPegawai . setHorizontalHeaderLabels ( [
31 ' ID ' , ' Nama ' , ' Alamat ' , ' T g l L a h i r ' , ' Kelamin ' ℄ )
32 s e l f . l i s t P e g a w a i . setColumnWidth ( 0 , 2 0 )
33 s e l f . l i s t P e g a w a i . setColumnWidth ( 1 , 1 5 0 )
34 s e l f . editNama . r e s i z e ( 2 0 0 , 3 0 )
35 s e l f . editAlamat . r e s i z e (200 ,100)
36 s e l f . listPegawai . r e s i z e (500 ,200)
37 s e l f . l a b e l N a m a . move ( 1 0 , 1 0 )
38 s e l f . l a b e l A l a m a t . move ( 1 0 , 4 0 )
39 s e l f . l a b e l T g l L a h i r . move ( 1 0 , 1 4 0 )
40 s e l f . l a b e l J e n i s . move ( 1 0 , 1 7 0 )
41 s e l f . editNama . move ( 1 0 0 , 1 0 )
42 s e l f . e d i t A l a m a t . move ( 1 0 0 , 4 0 )
43 s e l f . e d i t T g l L a h i r . move ( 1 0 0 , 1 4 0 )
44 s e l f . e d i t J e n i s . move ( 1 0 0 , 1 7 0 )
BAB 11. GRAPHICAL USER INTERFACE 103
45 s e l f . b u t t o n S i m p a n . move ( 1 0 0 , 2 0 0 )
46 s e l f . l i s t P e g a w a i . move ( 1 0 , 3 0 0 )
47 s e l f .
o n n e
t ( s e l f . buttonSimpan , SIGNAL ( '
l i
k e d ( )
') , s e l f . simpan )
48
49 def simpan ( s e l f ) :
50 row = s e l f . l i s t P e g a w a i . rowCount ( )
51 p i d = row+1
52 s e l f . l i s t P e g a w a i . setRowCount ( p i d )
53 s e l f . l i s t P e g a w a i . s e t I t e m ( row , 0 , QTableWidgetItem (
s t r ( pid ) ) )
54 s e l f . l i s t P e g a w a i . s e t I t e m ( row , 1 , QTableWidgetItem (
s e l f . editNama . t e x t ( ) ) )
55 s e l f . l i s t P e g a w a i . s e t I t e m ( row , 2 , QTableWidgetItem (
s e l f . editAlamat . toPlainText ( ) ) )
56 s e l f . l i s t P e g a w a i . s e t I t e m ( row , 3 , QTableWidgetItem (
s e l f . editTglLahir . text () ) )
57 s e l f . l i s t P e g a w a i . s e t I t e m ( row , 4 , QTableWidgetItem (
s e l f . e d i t J e n i s .
urrentText ( ) ) )
58 s e l f . editNama .
l e a r ( )
59 s e l f . editAlamat .
l e a r ( )
60 s e l f . e d i t J e n i s . setCurrentIndex (0)
61 s e l f . editNama . s e t F o
u s ( )
62
63
64 app = Qt . Q A p p l i
a t i o n ( s y s . a r g v )
65 fm = FormUtama ( )
66 fm . show ( )
67 app . exe
_ ( )
QTextEdit Untuk memasukkan tulisan juga, tapi bisa lebih dari satu baris.
QPushButton Tombol yang bila di-klik menjalankan suatu fungsi. Dalam hal
ini menyimpan data pegawai ke QTableWidget yang ada di bawahnya.
Dari sour
e tersebut dan menganalisa tampilan form, rasanya Anda bisa mema-
hami
ara penggunaan
lass di atas.
Obje
t Oriented
Programming
Kita membuat fungsi dengan tujuan esiensi sour
e, agar proses-proses yang
sama dapat diwakili dengan memanggil fungsi tertentu. Begitu juga pada pem-
buatan objek. Mari mulai pada kasus.
Ada sebuah le teks bernama barang.txt dengan isi seperti berikut ini.
1 1 Jeruk 34 9000
2 2 Mangga 8000
3 3 Pisang 7 10000
Pembuat le itu memastikan data barang tersimpan dengan lebar kolom
tetap . Kolom kode barang 3 karakter, nama barang 10 karakter, stok 2 karak-
ter, dan harga barang 8 karakter atau sisanya. Anda diminta memindahkan
data ini ke sebuah tabel di database. Mari mulai mempertimbangkan langkah-
langkah yang bisa ditempuh.
Andai saja kita bisa menggunakan split() yang bisa mengubah string menjadi
list, sehingga dengan mudah kolom pertama ada kode barang, kolom kedua
nama barang, dan seterusnya. Sayang sekali hal ini tidak dapat dilakukan.
Mengapa ?
Perhatikan baris Mangga dimana nilai stok kosong. Ini artinya kolom ketiga
menjadi harga barang. Tentu saja tidak konsisten dengan baris Jeruk dimana
kolom ketiga adalah stok. Idealnya pembuat le itu mengubah programnya
agar kalau stok kosong diberi angka 0. Namun posisi kita sedang tidak bisa
memaksa.
Baik, kita ikuti saja petunjuk pembuatnya dimana lebar kolom menjadi
a
uan. Sementara ini kita tidak perlu terlalu jauh bagaimana struktur tabelnya.
Dari sudut pandang Python saja dulu, tipe data apa yang
o
ok untuk mewakili
le ini. Untuk sementara anggap saja tipe data list yang sesuai karena ini
merupakan bentuk tabel.
106
BAB 12. OBJECT ORIENTED PROGRAMMING 107
1 import sys
2
3 f i l e n a m e = sys . argv [ 1 ℄
4 f = open ( f i l e n a m e )
5 for line in f . readlines () :
6 kode = l i n e [ : 3 ℄ . s t r i p ( )
7 nama = l i n e [ 3 : 3 + 1 0 ℄ . s t r i p ( )
8 stok = l i n e [3+10:3+10+2℄. s t r i p ( )
9 harga = l i n e [3+10+2:℄. s t r i p ( )
10 print [ kode , nama , stok , harga ℄
11 f .
lose ()
Jalankan.
1 $ python b a r a n g 1 . py barang . t x t
2 [ '1 ' , ' Jeruk ' , '34 ' , '9000 '℄
3 [ '2 ' , ' Mangga ' , ' ' , '8000 '℄
4 [ '3 ' , ' Pisang ' , '7 ' , '10000 '℄
Tahap ini sudah baik, dimana setiap nilai sudah dapat diwakili dalam vari-
abel kode, nama, stok, dan harga. Namun barang1.py masih kurang modular
karena masukannya berupa nama le yang diberikan melalui
ommand line.
1 def barang ( f i l e n a m e ) :
2 f = open ( f i l e n a m e )
3 rows = [℄
4 for line in f . readlines () :
5 kode = l i n e [ : 3 ℄ . s t r i p ( )
6 nama = l i n e [ 3 : 3 + 1 0 ℄ . s t r i p ( )
7 stok = l i n e [3+10:3+10+2℄. s t r i p ( )
8 harga = l i n e [3+10+2:℄. s t r i p ( )
9 row = [ kode , nama , s t o k , h a r g a ℄
10 r o w s . append ( row )
11 f .
lose ()
12 return rows
13
14
15 if __name__ == '__main__ ' :
BAB 12. OBJECT ORIENTED PROGRAMMING 108
16 import sys
17 f i l e n a m e = sys . argv [ 1 ℄
18 for in
row barang ( f i l e n a m e ) :
19 print row
Jalankan.
1 $ python b a r a n g 2 . py barang . t x t
2 [ '1 ' , ' Jeruk ' , '34 ' , '9000 '℄
3 [ '2 ' , ' Mangga ' , ' ' , '8000 '℄
4 [ '3 ' , ' Pisang ' , '7 ' , '10000 '℄
Hasil tetap sama, namun kini s
ript tidak hanya mengandung fungsi tetapi
juga bisa digunakan sebagai modul.
Sekarang aspek generalitas, atau tingkat ke-umum-an fungsi, dimana lebar se-
tiap kolom sudah ditetapkan di dalam fungsi (hard
ode). Bisakah ditingkatkan
generalitasnya ?
Kebutuhannya adalah ada le lain selain barang.txt dengan lebar setiap
kolom berbeda dengan barang.txt, namun sifatnya masih sama yaitu setiap
kolom memiliki lebar tertentu . Kalau barang.txt menggunakan lebar kolom
masing-masing 3, 10, 2, dan 8, mungkin pegawai.txt menggunakan 5, 30, 10,
50, dan 20. Jadi bukan hanya lebar kolomnya berbeda, jumlah kolomnya pun
berbeda.
Karena sudah bersifat umum sebaiknya nama fungsi dan nama lenya pun
umum. Buatlah xtable.py berikut.
18 import sys
19 f i l e n a m e = sys . argv [ 1 ℄
20 for in
row f i x t a b l e ( filename , [3 ,10 ,2 ,8℄) :
21 print row
Jalankan.
1 $ python f i x t a b l e . py barang . t x t
2 [ '1 ' , ' Jeruk ' , '34 ' , '9000 '℄
3 [ '2 ' , ' Mangga ' , ' ' , '8000 '℄
4 [ '3 ' , ' Pisang ' , '7 ' , '10000 '℄
Perhatikan lagi, hasil masih sama. Anda bisa uji dengan membuat pe-
gawai.txt.
Lalu xpegawai.py.
Jalankan.
1 $ python f i x p e g a w a i . py pegawai . t x t
2 [ '1 ' , 'BUMMI DWI PUTERA, ST ' , '1985 −08 −17 ' , 'L ' ℄
3 [ '2 ' , ' ARIEF SETIADI ' , '1972 −05 −02 ' , 'L ' ℄
4 [ '3 ' , 'CECEP ZAHRUDIN , ST ' , '1972 −06 −01 ' , 'L ' ℄
5 [ '4 ' , ' NITA PANDRIA' , '1976 −09 −19 ' , 'P ' ℄
6 [ '5 ' , 'ILHAM' , '1984 −11 −05 ' , 'L ' ℄
7 [ '6 ' , 'MIRANDA' , '1978 −10 −01 ' , 'P ' ℄
Lalu apa nilai yang
o
ok untuk stok Mangga yang tidak tertulis apapun alias
string hampa ? Apa tetap diisi sebagai string hampa ? Sebaiknya tidak, karena
kita akan menetapkan eld stok bertipe integer. Maka nilai yang
o
ok untuk
string hampa adalah None, alias objek hampa. Buatlah le FixTableType.py
berikut ini.
Jalankan.
1 $ python F i x T a b l e T y p e . py barang . t x t
2 [1 , ' Jeruk ' , 34 , 9000℄
3 [2 , ' Mangga ' , None , 8000℄
4 [3 , ' Pisang ' , 7, 10000℄
Perhatikan, tidak ada lagi kutip di kolom pertama, ketiga, dan keempat.
Selanjutnya ada kebutuhan untuk menyimpan kembali data tersebut ke se-
buah le sejenis, meski tidak harus ke barang.txt lagi. Fitur semakin bertambah
dimana:
Tipe integer
Bab 13
Kerja Sampingan
Anda diminta membuat sebuah program yang bertugas mengendalikan sebuah
GSM modem. Program ini bersifat daemon yang artinya selalu berjalan seolah
tanpa akhir. Tugas utamanya adalah mengirim SMS yang berasal dari seluruh
le yang ada di direktori /tmp/job. Hasil pengiriman SMS (berhasil / tidak)
dikirim ke SMS gateway induk melalui XMLRPC, inilah kerja sampingannya
atau sering disebut sebagai multi-thread .
Mengapa kita perlu multi-thread ?
Modem tersebut hanya bisa mengirim sebuah SMS pada satu saat yang
membutuhkan waktu 10 detik. Di sisi lain daemon ini harus mengabari status
pengiriman ke SMS gateway induk melalui XMLRPC yang membutuhkan waktu
5 detik. Bahkan kalau terkena masalah bandwidth XMLRPC
lient ini bisa
membutuhkan waktu 60 detik. Bayangkan kalau hanya single-thread.
Saat Thread 1
112
BAB 13. KERJA SAMPINGAN 113
2 import time
3 import os
4 from glob import glob
5
6
7
lass K i r i m ( Thread ) :
8 def __init__ ( s e l f , k) :
9 s e l f . k e r j a = True
10 s e l f . kabar = k
11 Thread . __init__ ( s e l f )
12
13 def run ( s e l f ) :
14 print t i m e . s t r f t i m e ( '%H:%M:%S ' ) , ' Kerja sampingan
dimulai '
15 while s e l f . kerja :
16 time . s l e e p ( 1 )
17 if not s e l f . kabar :
18
ontinue
19 hasil = s e l f . kabar [ 0 ℄
20 del s e l f . kabar [ 0 ℄
21 #s e l f . kabar = s e l f . kabar [ 1 : ℄
22 print '%s KABARI %s ' % ( t i m e . s t r f t i m e ( '%H:%M
:%S ' ) , hasil )
23
24 def join ( sel f ) :
25 print ' Kerja sampingan berakhir '
26 s e l f . kerja = False
27 Thread . j o i n ( s e l f )
28
29
30 job_dir = ' /tmp / j o b '
31 kabar = [℄
32
33 sampingan = Kirim ( kabar )
34 sampingan . s t a r t ( )
35
36 print t i m e . s t r f t i m e ( '%H:%M:%S ' ) , ' Pekerjaan utama dimulai
'
37 while True :
38 time . s l e e p ( 1 )
39 if not os . path . e x i s t s ( job_dir ) :
40
ontinue
41 filenames = g l o b ( '%s / * ' % j o b _ d i r )
42 if not filenames :
43
ontinue
44 filename = filenames [ 0 ℄
BAB 13. KERJA SAMPINGAN 114
45 f = open ( f i l e n a m e )
46 job = f . read ( )
47 f .
lose ()
48 o s . remove ( f i l e n a m e )
49 print '%s KERJAKAN %s ' % ( t i m e . s t r f t i m e ( '%H:%M:%S ' ) ,
job )
50 k a b a r . append ( j o b )
51
52 print ' Pekerjaan utama berakhir '
53 sampingan . j o i n ( )
Jalankan.
1 $ python t e s t t h r e a d . py
2 04:56:54 Pekerjaan utama dimulai
3 04:56:54 Kerja sampingan dimulai
1 $ mkdir /tmp / j o b
1 $ e ho h e l l o > /tmp / j o b / h e l l o . t x t
1 0 4 : 5 6 : 5 6 KERJAKAN hello
2 04:56:57 KABARI hello
Pointer
Perlu diperhatikan variabel kabar yang bertipe list (baris 30). Ini adalah vari-
abel bersama , artinya dapat diolah baik oleh thread 1 maupun thread 2. Di
sini berlaku apa yang disebut pointer yang artinya alokasi memori pada baris
30 dengan baris 10
1 s e l f . kabar = k
1 del s e l f . kabar [ 0 ℄
1 s e l f . kabar = s e l f . kabar [ 1 : ℄
Namun teknik ini akan membuat alokasi memori yang baru dimana thread 2
tidak lagi menggunakan variabel kabar sebagaimana yang digunakan oleh thread
1.
Mudah-mudahan Anda paham apa yang dimaksud dengan multi-thread ini.
Bab 14
SMS Gateway
SMS Gateway adalah salah satu produk RAB yang memanfaatkan Python dan
PostgreSQL. Akses ke database menggunakan SQLAl
hemy dan Elixir. Diran-
ang semodular mungkin agar mudah dipakai oleh sistem lainnya yang bukan
Python, bukan PostgreSQL, bahkan bukan Linux.
Produk ini juga menerapkan teknik event driven dan plug-in.
14.1 Pemasangan
Proses instalasi akan meminta Anda menyesuaikan le /et
/im/gw/
on-
g.py. File ini perlu diisi dengan otentikasi ke database yang sudah dibuat
tadi.
Kemudian jalankan:
im-gw juga otomatis hidup saat komputer dihidupkan. Anda bisa memantau
log-nya dengan
ara:
115
BAB 14. SMS GATEWAY 116
Tekan Ctrl-C untuk mengakhiri. Tapi sebaiknya tetap terpantau, dan Anda
bisa gunakan konsole lain untuk aktivitas berikutnya.
Untuk mengirim dan menerima SMS yang sebenarnya dibutuhkan pengen-
dali modem:
Paket ini juga akan membuat tabel, menggunakan kongurasi yang sama
dengan im-gw.
Pasanglah modem GSM atau CDMA. Merk yang sudah teruji adalah Wave-
om, iTegno, dan Multite
h. USB devi
e lebih disarankan karena mendukung
hotplug, dimana saat modem ditan
apkan pengendalinya otomatis aktif. Anda
bisa periksa dengan perintah:
1 $ ps ax | g r e p modem
2 5627 ? SN 0:06 / u s r / b i n / python / u s r / b i n /modem−h o t p l u g
3 28464 ? Sl 0:01 python / u s r / b i n /modem / d e v / ttyUSB0
Anda bisa menyebutkan semua serial port yang ada pada le /et
/im/-
modem/modem.
onf:
1 [ devi
e ℄
2 ; devi
e di / dev / t t y
3 p o r t = USB0 USB1 USB2 USB3 USB4 USB5 USB6 USB7 S0 S4 S5
S6 S7
1 $ ps ax | g r e p modem
2 11211 ? Rl 10:29 python / u s r / b i n /modem / d e v /
ttyS0
1 $ sudo ls / v a r / l o g /modem
2 510012541218911. l o g
Bila Anda sudah berjumpa kalimat yang berawalan Serving seperti di atas,
maka modem sudah siap.
Angka itu disebut dengan IMEI alias identitas
hip / SIM
ard. Jika kom-
puter membutuhkan informasi devi
e port untuk mengendalikan modem, maka
manusia / user membutuhkan IMEI sebagai identitas
hip yang ada di dalam
modem. Aktivitas menerima dan mengirim SMS tentu melekat pada
hip, bukan
pada modem. Karena itu penggunaan IMEI pada nama log adalah yang paling
tepat untuk menjaga konsistensi history.
Lagi pula devi
e port yang digunakan modem USB kadang berubah. Saat
ini mungkin modem dikenali di USB0. Coba Anda lepas dan pasang lagi di
tempat yang sama, bisa jadi kini USB1 yang digunakannya.
14.1.2 Database
Saat /usr/bin/modem mulai mengendalikan sebuah modem, ia melaporkan ke
/usr/bin/im-gw bahwa IMEI 510012541218911 baru saja hidup. Kejadian ini
disebut sebagai startup. Saat itulah im-gw memeriksa keberadaan IMEI terse-
but di tabel im.agent. Kalau belum ada ia tambahkan, dan kalau sudah ada ia
perbaharui statusnya.
Status 0 berarti modem siap, status negatif berarti sebaliknya. Alasan untuk
status negatif bisa Anda lihat di tabel im.status.
4 −−−−−−+−−−−−−−−+−−−−−−−−−−−−−−−−−+−−−−−−−−−−−−−−−+−−−−−−−−−−−−−−
Diterima
Ada dua paket utama di sini, yaitu im-gw dan im-modem. Keduanya terhubung
sebagaimana pada gambar 14.1. Lalu mengapa harus ada dua paket ?
Meski judul tulisan ini adalah SMS Gateway, namun pada konsepnya sistem
ini dapat disanding dengan paket instant messenger seperti Yahoo! Messenger
dan XMPP (Jabber, GTalk). Keduanya ada di paket im-ym dan im-xmpp.
Jadi im-modem, im-ym, dan im-xmpp sejajar kedudukannya. Kalau im-modem
memerlukan sik modem, maka im-ym dan im-xmpp membutuhkan koneksi
Internet.
Jadi bila Anda ingin men
oba sistem ini namun belum memiliki modem,
maka bisa gunakan im-ym dan im-xmpp.
1 $ ps ax | g r e p ym
2 2339 ? Sl 24:44 python / u s r / b i n /ym i n f o r a b
Sekarang
oba add buddy dari Yahoo! Messenger
lient seperti Pidgin. Ten-
tu saja gunakan Yahoo! a
ount yang lain. Daemon ym se
ara otomatis akan
menambahkannya ke dalam daftar.
Selanjutnya kirim pesan seperti biasa, lalu lihat log-nya:
Sekarang perhatikan kolom jalur yang berisi 5. Itu artinya jalur ym. Sedan-
gkan jalur modem berisi 1 (default). Daftar jalur ini ada di tabel jalur.
14.3.2 XMPP
Jika Anda punya a
ount di Gmail maka Anda dapat
hatting dengan user
Gmail lainnya. Namun sebenarnya Anda dapat
hatting dengan user dari server
lain yang menggunakan protokol XMPP seperti jabber.org atau jabber.rab.
o.id.
Ya, seperti email, protokol XMPP memungkinkan user dari server berbeda da-
pat saling mengirim pesan.
Jika Anda berminat menggunakan XMPP untuk
hatting dengan server,
pasang paket im-xmpp.
1 u s e r s = { ' i n f o r a b g m a i l .
om ' :
2 { ' password ' : ' 1234 ' , ' sasl ' : True ,
3 ' port ' : 5223 , ' server ' : ' t a l k . g o o g l e .
om ' }
4 }
Sesuaikan inforab dan 1234. Setelah disimpan tunggu satu menit hingga
daemon-nya up. Setelah hidup, Anda bisa lakukan pengujian yang serupa seper-
ti ym.
Jika Anda ingin menggunakan server lokal, bisa
oba daftar ke jabber.rab.
o.id
menggunakan Pidgin. Lalu sesuaikan /et
/im/xmpp/
ong.py seperti
ontoh
berikut.
1 u s e r s = { ' i n f o r a b g m a i l .
om ' :
2 { ' password ' : ' 1234 ' , ' sasl ' : True ,
3 ' port ' : 5223 , ' server ' : ' t a l k . g o o g l e .
om ' } ,
4 ' i n f o j a b b e r . rab .
o . i d ' : ' 1234 '
5 }
Ya, im-xmpp juga dapat menghidupkan lebih dari satu a
ount. Kebetulan
jabber.rab.
o.id menggunakan kongurasi yang lebih sederhana sebagaimana
ontoh di atas.
Anda telah memiliki banyak pelanggan dan ingin mengirim pesan yang sama
ke mereka. Dengan mudah lakukan query berikut.
Sayangnya untuk jumlah penerima yang sangat banyak tidak bisa semudah
itu, karena /usr/bin/modem memiliki nilai job timeout yang default-nya 420 de-
tik alias 7 menit. Jika setiap pesan membutuhkan waktu 10 detik untuk dikirim,
maka hanya 42 pesan saja yang akan dikirim. Selebihnya akan dilaporkan oleh
/usr/bin/modem sebagai status -9 alias Timeout.
Menaikkan nilai timeout di /et
/im/modem/modem.
onf bisa juga jadi so-
lusi, namun tidak disarankan. Teknik yang paling pas adalah menyiapkan dae-
mon baru yang memantau nilai eld job. Jika job lebih besar dari 5 maka tidak
dilakukan INSERT ke im.antrian.
Untuk kebutuhan ini sudah disiapkan paket im-broad
ast.
Untuk mengirim pesan kita perlu melakukan INSERT ke dua tabel, yaitu
im.broad
ast dan im.broad
ast_penerima. Tabel pertama berisi pesan, sedan-
gkan tabel kedua berisi penerimanya. Kedua tabel ini akan diproses oleh daemon
/usr/bin/im-broad
ast untuk disalin ke tabel im.antrian.
Pertama kita memerlukan nilai ID untuk broad
ast yang baru.
BAB 14. SMS GATEWAY 123
Field judul hanya untuk keterangan saja. Field pesan-lah yang nanti akan
dikirim. Berikutnya tambahkan penerima pesan.
Jalur default yang digunakan adalah 1 (modem). Untuk jalur lainnya ser-
takan eld jalur.
Web
15.1 Django
15.2 Webpy
124
Bab 16
Hosting
16.1 Virtualmin
Ingin berbisnis web hosting ? Terbentur biaya untuk pengadaan CPanel ? Saat-
1
nya menggunakan Virtualmin . Ingin membidik pangsa developer Python se-
lain pangsa PHP ? Anda masih bisa mengubah kemampuan Virtualmin. Tidak
punya IP publik statik ? Hanya dapat IP publik dinamik ? Jangan ragu, tetap
gunakan Virtualmin.
Virtualmin merupakan antarmuka web untuk mengatur berbagai hal terkait
dengan bisnis web hosting Anda. Ia memberikan kemudahan dalam pendaf-
taran domain, pemberian hak akses, dan juga kuota. Ia merupakan produk open
sour
e yang mengatur berbagai aplikasi standar lainnya seperti Apa
he, PHP,
Postx, Dove
ot, PostgreSQL, dst. Namun begitu, ia menghindari "sentuhan
sihir" alias tetap mengikuti aturan-aturan yang ditetapkan masing-masing ap-
likasi tersebut.
1 http://virtualmin.
om
2 http://ubuntu.
om
3 Graphi
al User Interfa
e
125
BAB 16. HOSTING 126
Amannya pilih yang mana ? Pilihlah Ubuntu 10.04 i386 Desktop Edition .
4
ISO bisa di-burn ke CD-ROM 700 MB. Rata-rata motherboard sekarang su-
dah mendukung boot melalui ashdisk. Jadi ada baiknya burn ISO ke ashdisk
menggunakan aplikasi Unetbootin, tersedia untuk sistem operasi Windows dan
Linux.
Setelah di-burn, boot, dan ikuti langkah-langkah petunjuk pemasangannya.
Sebaiknya pilihlah Bahasa Indonesia agar default format sesuai dengan Indone-
sia seperti format tanggal (dmy), pemisah ribuan (thousand separator), dsb.
Setelah pemasangan selesai dan server sudah di-boot, ubahlah hak akses
pada home dire
tory Anda agar user lain tidak bisa melihat isinya.
Anda tidak perlu melakukan ini jika membuat user baru melalui Virtualmin
nanti.
$ telnet 203.130.231.120 80
Jika Anda mendapati baris "Es
ape
hara
ter is" berarti gateway berfungsi
dengan baik:
Trying 203.130.231.120...
Conne
ted to 203.130.231.120.
Es
ape
hara
ter is '^℄'.
Oh iya, juga sesuaikan /et
/resolv.
onf agar Anda bisa memanggil dengan nama
(DNS), misalnya:
nameserver 203.130.231.120
$ telnet google.
om 80
Trying 74.125.235.20...
Conne
ted to google.
om.
Es
ape
hara
ter is '^℄'.
Sesuaikanlah gateway dan DNS ini dengan menanyakan ke Internet Servi
e
Provider Anda.
Server Anda terhubung dengan modem ADSL ? Biasanya IP sudah dis-
et se
ara otomatis melalui mekanisme DHCP. Meski begitu sebaiknya Anda
memastikan IP LAN tetap statik. Bisa diset melalui menu tadi, atau melalui
modem ADSL-nya dimana biasanya modem akan menentukan MAC address
00:1f:3
:e0:66:56 mendapat IP 192.168.1.2 (
ontoh).
$ sudo sh install.sh
Saat ia menanyakan hostname, jawablah sesuai nama domain hosting yang Anda
kelola:
FATAL - in /root/virtualmin-install.log
Kadang selama proses unduh terjadi "
onne
tion refused". Mungkin server
Virtualmin sedang di-restart. Tunggulah beberapa saat, dan jalankan lagi s
ript
instalasi seperti tadi.
$ sudo sh install.sh
Biasanya ia mengerti untuk tidak melakukannya dari awal.
BAB 16. HOSTING 128
$ sudo gedit
Namun jika Anda terbiasa dengan konsole, vi dan nano sudah tersedia. Bagi
yang terbiasa dengan vi ada baiknya pasang vim (vi improved) untuk kenya-
manan:
Aktifkan pen
arian pintar dimana kalau Anda menuliskan huruf ke
il semua
saat pen
arian maka tidak mempedulikan huruf ke
il ataupun besar (in
ase-
sensitive). Namun jika Anda menyertakan huruf besar maka
ase-sensitive
berlaku.
Selesai dan simpanlah. Kongurasi ini se
ara otomatis juga berlaku bagi
user Anda nantinya. Sehingga kenyamanan programmer makin bertambah.
BAB 16. HOSTING 129
Pastikan direktori /home sebagai basis suphp, ubah /et
/suphp/suphp.
onf,
ganti baris
do root=/var/www:${HOME}/publi _html
menjadi
do root=/home
Ubahlah /et /php5/ gi/php.ini agar pengunjung web nyaman unggah video:
1 m a x _ e x e
u t i o n _t i m e = 1 0 0 0
2 max_input_time = 1 0 0 0
3 memory_limit = 1 2 8M
4 p o s t _ m a x _ s i z e = 1 0 0M
5 u p l o a d _ m a x _ f i l e s i z e = 1 0 0 0M
MECHANISMS="pam"
menjadi
MECHANISMS="shadow"
Restart daemon-nya:
16.1.7 PostgreSQL
Sebaiknya Anda periksa default en
oding yang digunakan PostgreSQL.
https://127.0.0.1:10000
Namun jika server sudah berada di remote, Anda bisa gunakan IP publiknya
sehingga url menjadi (
ontoh):
https://202.59.201.67:10000
Jika IP publik server adalah statik, maka lanjutkan klik module
onguration
yang dimaksud. Atau se
ara menu melalui System Settings, Virtualmin Con-
guration. Pada pilihan Conguration Category, pilih Network settings, lalu:
Default IP address for DNS re
ords: Automati
ally dete
t ex-
ternal address
Klik Save. Jangan lupa mengatur modem ADSL untuk mengarahkan seluruh
permintaan dari luar ke server 192.168.1.2. Mekanisme ini sering disebut sebagai
port forwarding, atau ada juga yang bilang DMZ.
Jika Anda tidak pernah memesan IP publik statik pada ISP, hampir di-
pastikan Anda hanya mendapat IP publik dinamik. Dengan demikian abaikan
saja urusan DNS di atas, karena DNS yang Anda butuhkan perlu ditangani
server lain yang memiliki IP publik statik, misalnya dyndns.org.
Yang lebih mengkhawatirkan lagi bila server tidak mendapatkan IP publik.
Ini artinya server tidak bisa disentuh (ba
a: di- route ) dari luar. Praktis Anda
tidak bisa berbisnis hosting. Untuk memastikannya,
oba minta teman Anda
yang ada di "seberang" sana untuk mengakses http://180.252.150.215.
Sesuaikanlah IP-nya sebagaimana yang dilaporkan Virtualmin di atas. Jika
ia mendapatkan pesan:
It works!
Agar lebih nyaman dalam memasang berbagai aplikasi dari GitHub dan
Bitbu
ket, pasanglah aplikasi pengunduhnya:
Juga Virtual Environment agar user dimudahkan dalam memasang modul Python
lainnya tanpa perlu memanggil Anda sebagai pengelola hosting.
Virtualmin sudah menyediakan apa yang disebut Server Template. Saat pendaf-
taran domain, admin diberikan kesempatan memilih bahasa apa yang akan di-
gunakan pelanggannya. Default-nya adalah PHP, dan alternatif lain adalah
BAB 16. HOSTING 133
Klik Create and Next. Pada bagian Edit template se
tion, pilih Apa
he website.
Ini untuk mengganti form isian dengan hal-hal yang bersifat Apa
he. Pada
bagian Dire
tives and settings for new websites, dan pada radio button Apa
he
dire
tives below tambahkan baris-baris WSGI berikut ini (paling bawah):
Klik Save.
1 #! / usr / b i n / python
BAB 16. HOSTING 134
2
3 import os
4 import sys
5
6 if o s . e n v i r o n [ 'VIRTUALSERVER_ACTION ' ℄ == 'CREATE_DOMAIN' :
7 o s . system ( '
p −r / u s r / l o
a l / e t
/ v i r t u a l m i n / w s g i %s ' % (
8 o s . e n v i r o n [ 'VIRTUALSERVER_HOME' ℄ ) )
9 o s . s y s t e m ( '
d %s / w s g i ; ln −s . wsgi ' % os . environ [ '
VIRTUALSERVER_HOME' ℄ )
10 o s . s y s t e m ( ' v i r t u a l e n v %s / e n v ' % o s . e n v i r o n [ '
VIRTUALSERVER_HOME' ℄ )
11 o s . s y s t e m ( '
hown −R %s .% s %s / w s g i %s / e n v ' % (
12 o s . e n v i r o n [ 'VIRTUALSERVER_USER ' ℄ ,
13 o s . e n v i r o n [ 'VIRTUALSERVER_GROUP ' ℄ ,
14 o s . e n v i r o n [ 'VIRTUALSERVER_HOME' ℄ ,
15 o s . e n v i r o n [ 'VIRTUALSERVER_HOME' ℄ ) )
Lalu siapkan direktori /usr/lo
al/et
/virtualmin/wsgi yang nantinya akan di-
taruh di $HOME/ :
$ sudo mkdir -p /usr/lo
al/et
/virtualmin/wsgi
1 import os
2 import sys
3 import time
4 import signal
5 import threading
6 import atexit
7 import Queue
8
9 _interval = 1.0
5 Interpreter Python mengizinkan kita untuk mengubah le *.py selama s
ript sedang ber-
jalan (runtime ). Namun perubahan itu berfungsi saat s
ript itu dijalankan ulang.
BAB 16. HOSTING 135
10 _times = {}
11 _files = [℄
12
13 _running = F a l s e
14 _queue = Queue . Queue ( )
15 _ l o
k = t h r e a d i n g . Lo
k ( )
16
17 def _ r e s t a r t ( path ) :
18 _queue . p u t ( True )
19 prefix = ' monitor ( p i d=%d ) : ' % o s . g e t p i d ( )
20 print >> s y s . s t d e r r , '%s Change dete
ted to \ '% s \ ' . '
% ( prefix , path )
21 print >> s y s . s t d e r r , '%s Triggering pro
ess restart . '
% prefix
22 os . k i l l ( os . getpid ( ) , s i g n a l . SIGINT )
23
24 def _modified ( path ) :
25 try :
26 # I f path doesn ' t denote a f i l e and were
previously
27 # t r a
k i n g i t , then i t has been removed or t h e
f i l e type
28 # has
hanged so f o r
e a r e s t a r t . I f not
previously
29 # t r a
k i n g t h e f i l e then we
an i g n o r e i t as
probably
30 # pseudo r e f e r e n
e su
h as when f i l e e x t r a
t e d
from a
31 #
o l l e
t i o n o f modules
o n t a i n e d in a z i p f i l e .
32
33 if not os . path . i s f i l e ( path ) :
34 return path in _times
35
36 # Che
k f o r when f i l e l a s t m o d i f i e d .
37
38 mtime = o s . s t a t ( p a t h ) . st_mtime
39 if path not in _times :
40 _ t i m e s [ p a t h ℄ = mtime
41
42 # For
e r e s t a r t when m o d i f i
a t i o n time has
hanged , even
43 # i f time now o l d e r , as t h a t
o u l d i n d i
a t e o l d e r
file
44 # has been r e s t o r e d .
45
46 if mtime != _times [ path ℄ :
BAB 16. HOSTING 136
47 return True
48 ex
ept :
49 # I f any e x
e p t i o n o
ured , l i k e l y t h a t f i l e has
been
50 # been removed j u s t b e f o r e s t a t ( ) , so f o r
e a
restart .
51
52 return True
53
54 return False
55
56 def _monitor ( ) :
57 while 1:
58 # Che
k m o d i f i
a t i o n times on a l l f i l e s in s y s .
modules .
59
60 for module in s y s . modules . v a l u e s ( ) :
61 if not h a s a t t r ( module , ' __file__ ' ) :
62
ontinue
63 p a t h = g e t a t t r ( module , ' __file__ ' )
64 if not path :
65
ontinue
66 if os . path . s p l i t e x t ( path ) [ 1 ℄ in [ ' . py
' , '.
pyo ' , ' . pyd ' ℄ :
67 path = path [ : −1℄
68 if _modified ( path ) :
69 return _ r e s t a r t ( path )
70
71 # Che
k m o d i f i
a t i o n times on f i l e s whi
h have
72 # s p e
i f i
a l l y been r e g i s t e r e d f o r monitoring .
73
74 for path in _files :
75 if _modified ( path ) :
76 return _ r e s t a r t ( path )
77
78 # Go t o s l e e p f o r s p e
i f i e d i n t e r v a l .
79
80 try :
81 return _queue . g e t ( t i m e o u t=_ i n t e r v a l )
82 ex
ept :
83 pass
84
85 _ t h r e a d = t h r e a d i n g . Thread ( t a r g e t=_monitor )
86 _ t h r e a d . setDaemon ( True )
87
88 def _exiting () :
BAB 16. HOSTING 137
89 try :
90 _queue . p u t ( True )
91 ex
ept :
92 pass
93 _thread . j o i n ( )
94
95 a t e x i t . r e g i s t e r ( _exiting )
96
97 def t r a
k ( path ) :
98 if not path in _files :
99 _ f i l e s . append ( p a t h )
100
101 def s t a r t ( i n t e r v a l =1.0) :
102 global _interval
103 if i n t e r v a l < _interval :
104 _interval = i n t e r v a l
105
106 global _running
107 _lo
k . a
q u i r e ( )
108 if not _running :
109 prefix = ' monitor ( p i d=%d ) : ' % o s . g e t p i d ( )
110 print >> s y s . s t d e r r , '%s Starting
hange monitor .
' % prefix
111 _ r u n n i n g = True
112 _thread . s t a r t ( )
113 _lo
k . r e l e a s e ( )
13 s y s . p a t h . append ( o s . p a t h . d i r n a m e ( o s . p a t h . a b s p a t h ( __file__ )
))
14 env_ver = ' . ' . j o i n ( map ( lambda x: str (x) , sys . version_info
[:2℄) )
15 env_path = o s . p a t h . d i r n a m e ( o s . p a t h . d i r n a m e ( o s . p a t h .
a b s p a t h ( __file__ ) ) ) + \
16 ' / e n v / l i b / p y t h o n%s / s i t e −p a
k a g e s ' % env_ver
17 s y s . p a t h . append ( env_path )
18
19 #os . e n v i r o n [ 'DJANGO_SETTINGS_MODULE ' ℄ = ' myproje
t .
settings '
20 #import django .
ore . h a n d l e r s . wsgi
21 #a p p l i
a t i o n = django .
ore . h a n d l e r s . wsgi . WSGIHandler ( )
22
23 import monitor
24 monitor . s t a r t ( i n t e r v a l =1.0)
http://sabilawebhosting. om
Hello world!
hampir dipastikan domain tersebut belum sepenuhnya dikenal oleh para ISP.
Jika Anda browsing di server pastikan baris berikut ini ada di urutan teratas
/et
/resolv.
onf :
nameserver 127.0.0.1
Namun jika Firefox Anda berada di mesin berbeda, pastikan DNS teratas adalah
IP server, masih di /et
/resolv.
onf dimana Firefox berada:
BAB 16. HOSTING 139
nameserver 202.59.201.67
Anda bisa membuka Virtualmin dengan subdomain admin, yaitu dengan url:
http://admin.sabilawebhosting. om
Hal serupa dapat dilakukan oleh pelanggan Anda sesuai domain mereka masing-
masing.
Sedangkan untuk mail, mereka bisa mengunjungi subdomain webmail, dalam
hal ini
ontohnya adalah:
http://webmail.sabilawebhosting. om.
$
d wsgi
$ ../env/bin/django-admin.py startproje
t myproje
t
1 import os , sys
2
3 sys . stdout = sys . stderr
4 s y s . p a t h . append ( o s . p a t h . d i r n a m e ( o s . p a t h . a b s p a t h ( __file__ )
))
5 env_ver = ' . ' . j o i n ( map ( lambda x: str (x) , sys . version_info
[:2℄) )
6 env_path = o s . p a t h . d i r n a m e ( o s . p a t h . d i r n a m e ( o s . p a t h .
a b s p a t h ( __file__ ) ) ) + \
7 ' / e n v / l i b / p y t h o n%s / s i t e −p a
k a g e s ' % env_ver
8 s y s . p a t h . append ( env_path )
9
10 o s . e n v i r o n [ 'DJANGO_SETTINGS_MODULE' ℄ = ' myproje
t .
settings '
11 import django .
ore . handlers . wsgi
6 http://djangoproje
t.
om
7 Python virtual environment otomatis terbentuk saat pembuatan domain.
BAB 16. HOSTING 140
12 a p p l i
a t i o n = d j a n g o .
o r e . h a n d l e r s . w s g i . WSGIHandler ( )
13
14 import monitor
15 monitor . s t a r t ( i n t e r v a l =1.0)
It worked!
Hello World!
yang berasal dari le wsgi/wsgi_handler.py. Jika tadi Anda pilih Default Set-
tings pada Server
onguration template, seharusnya Anda menjumpai pesan:
Forbidden
141
Indeks
__name__, 35 integer, 11
dropdb, 43
pg_dump, 54
dropuser, 42
pg_restore, 54
epo h, 29 plpgsql, 6
eval(), 20 plpython, 6
postgresql.
onf, 48
oat, 11 PRIMARY KEY, 44
for, 16 print, 9, 20
formatting, 17, 19 psql, 6, 43
fullpath, 54
rata kanan, 55
Gnome, 7 raw_input(), 10, 27
142
INDEKS 143
serial, 46
sisa pembagian, 18
SQLAl
hemy, 6
string, 9, 11
sudo, 42
Symbian, 5
text editor, 7
time(), 29
tipe data di
tionary, 26
tipe data oat, 18
tipe data integer, 18
tipe data list, 20
transa
tion, 72
transa
tion, auto
ommit, 72
type(), 17
Ubuntu, 6
Unix, 5
Unix time, 29
UPDATE, 50
upper(), 9
variabel, 11
vi, 7
while, 15