Anda di halaman 1dari 144

Database PostgreSQL, Pemrograman Python,

dan SMS Gateway

RAB Linux Indonesia

2012

Daftar Isi
1 Alasan
2 Pemasangan
3 Hello World!
3.1

Variabel dan Tipe Datanya

3.2

Kondisi

3.3

Perulangan

4 Tipe Data

5
6
9

. . . . . . . . . . . . . . . . . . . . .

10

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17

4.1

String

4.2

Bilangan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

18

4.2.1

Konversi Tipe Data

. . . . . . . . . . . . . . . . . . . . .

19

4.2.2

Formatting

. . . . . . . . . . . . . . . . . . . . . . . . . .

19

4.2.3

Kalkulator

. . . . . . . . . . . . . . . . . . . . . . . . . .

20

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

20

4.3

List

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14

. . . . . . . . . . . . . . . . . . . . . . . . .

17

4.3.1

Pemenggalan

4.3.2

Keberadaan Elemen

. . . . . . . . . . . . . . . . . . . . .

22

21

4.3.3

Mengubah Elemen . . . . . . . . . . . . . . . . . . . . . .

25

4.4

Di tionary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

26

4.5

Waktu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

28

5 Modularitas

31

5.1

Membuat Fungsi

. . . . . . . . . . . . . . . . . . . . . . . . . . .

5.2

Membuat Modul

. . . . . . . . . . . . . . . . . . . . . . . . . . .

33

5.3

Sear h Path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

35

6 Fungsi
6.1

Memanggil Dirinya Sendiri

6.2

Format Uang

7 Database
7.1

Tabel

. . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7.1.1

Sequen e

. . . . . . . . . . . . . . . . . . . . . . . . . . .

7.1.2

Mengubah Struktur

. . . . . . . . . . . . . . . . . . . . .

32

37

37
37

42

44
46

49

DAFTAR ISI

7.2

View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

51

7.3

Ba kup dan Restore

. . . . . . . . . . . . . . . . . . . . . . . . .

53

. . . . . . . . . . . . . . . . . . . . . . . . . . .

54

Fungsi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

55

7.4.1

PL/pgSQL

. . . . . . . . . . . . . . . . . . . . . . . . . .

56

7.4.2

PL/Python

. . . . . . . . . . . . . . . . . . . . . . . . . .

61

7.3.1
7.4

En oding

8 Python Akses Database


8.1

A tive Re ord . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8.2

Auto Commit . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8.3

Syn hronizer

8.4

63

64
71

. . . . . . . . . . . . . . . . . . . . . . . . . . . . .

73

8.3.1

Aspek Keamanan . . . . . . . . . . . . . . . . . . . . . . .

74

8.3.2

Tambah, Perbaharui, Hapus . . . . . . . . . . . . . . . . .

Migrasi dari Database Lain

. . . . . . . . . . . . . . . . . . . . .

9 Lintas Sistem

76
78

80

9.1

Command Line . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9.2

File

9.3

Database

9.4

XMLRPC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

84

9.4.1

PHP sebagai XMLRPC Client

. . . . . . . . . . . . . . .

87

9.4.2

Drupal . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

88

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10 Pengemasan

10.1 Paket Debian . . . . . . . . . . . . . . . . . . . . . . . . . . . . .


10.2 Debian Repository

80
82
83

90

90

. . . . . . . . . . . . . . . . . . . . . . . . . .

95

10.3 Remastering Ubuntu . . . . . . . . . . . . . . . . . . . . . . . . .

96

11 Graphi al User Interfa e

99

11.1 Orientasi Objek . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100

11.2 Daftar Pegawai . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101

12 Obje t Oriented Programming

106

12.1 Lebih Terstruktur . . . . . . . . . . . . . . . . . . . . . . . . . . . 107

12.2 Lebih Umum

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108

12.3 Tingkat Kerumitan . . . . . . . . . . . . . . . . . . . . . . . . . . 109

13 Kerja Sampingan
14 SMS Gateway

112
115

14.1 Pemasangan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115


14.1.1 IMEI Chip
14.1.2 Database

. . . . . . . . . . . . . . . . . . . . . . . . . . 117
. . . . . . . . . . . . . . . . . . . . . . . . . . . 118

14.2 Hello world! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118


14.3 Instant Messenger Gateway
14.3.1 Yahoo! Messenger

. . . . . . . . . . . . . . . . . . . . . 119

. . . . . . . . . . . . . . . . . . . . . . 119

14.3.2 XMPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121

DAFTAR ISI

14.4 Broad ast . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122

15 Web

124

15.1 Django . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124

15.2 Webpy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124

16 Hosting

16.1 Virtualmin

125

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 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
16.2 Google Apps

. . . . . . . . . . . . . . . . . . . . . . . . . . 139

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 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.

Bab 1

Alasan
Mengapa Python merupakan bahasa yang tepat untuk pembuatan berbagai
aplikasi ? Berikut ini alasannya.

Multiplatform

Python merupakan bahasa pemrograman yang tersedia di berba-

gai platform seperti Linux, Windows, Ma , Unix. Bahkan sudah tersedia

di platform handphone seperti Symbian dan Android.

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).

Lalu mengapa PostgreSQL dipilih sebagai media penyimpanan datanya ?

Multiplatform
Lengkap

PostgreSQL tersedia di Linux, Windows, Ma , dan Unix.

PostgreSQL tergolong lengkap dan mudah dikembangkan.

Memili-

ki sifat umum traditional database seperti transa tion, stored pro edure
(fun tion), dan trigger. Bahkan fun tion bisa ditulis dalam berbagai ba-

hasa (tidak hanya SQL), Python, Perl, Shell, dan Java adalah ontoh bahasa yang didukungnya. Ia juga memiliki modul khusus untuk kebutuhan
GIS (Geographi Information System).

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:
1

sudo

a p t g e t

install

postgresql

p o s t g r e s q l p l p y t h o n

8.4

plpython digunakan saat kita membuat fun tion di PostgreSQL, alternatif


lain dari plpgsql yang terpasang se ara default.
Pasang SQLAl hemy agar Python bisa menggunakan PostgreSQL:
1

sudo

a p t g e t

install

python s q l a l h e m y

python p s y o p g 2

Saat pemasangan paket postgresql se ara otomatis paket postgresql- lient-8.4


terpasang. Paket ini memuat psql yang digunakan untuk terhubung ke PostgreSQL server, se ara ommand line. Ada baiknya Anda juga memasang versi
web-nya:
1

sudo

a p t g e t

install

phppgadmin

Kadang web server Apa he tidak otomatis hidup:


1

sudo

/ e t / i n i t . d/ apa he2

start

Se ara default Apa he hidup otomatis saat komputer boot. Lalu buatlah symlink phppgadmin:
1

sudo

ln

/ u s r / s h a r e / phppgadmin

/ v a r /www/

Kemudian di browser (sebaiknya Firefox) buka url:

BAB 2.

PEMASANGAN

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

a p t g e t

install

vim

Kemudian sesuaikan /et /vim/vimr ,


1

sudo

vi

/ e t / vim / v i m r

Biasanya option sudah disediakan, Anda tinggal menghapus tanda kutip di


awal option. Aktifkan pewarnaan agar nyaman saat memba a sour e:
1

" Vim5 and

later

versions

Un ommenting
2

"

syntax

line

enables

the

support

syntax

highlighting .

next

syntax

highlighting

by

default .

on

Saat Anda membuka le untuk keduakalinya, maka kursor langsung menuju
ke lokasi sebelumnya.
1

" Un omment
position

"

if

reopening

the

to

h a v e Vim jump

to

the

last

file

h a s ( " auto md " )


au

BufReadPost
l i n e (" $ ")

following

when

if

l i n e ( " ' \ " " ) > 0 && l i n e ( " ' \ " " ) <=

exe

" normal

g '\""

endif

endif
Menjorok otomatis (auto indent), dan penekanan tombol TAB diganti dengan SPACE 4 kali:

" Un omment
rules

"

dete ted
filetype

"

if

the

following

a ording

to

filetype .

to

h a v e Vim

load

indentation

the

Per

default

D e b i a n Vim

only

load

spe ifi

plugins .
h a s ( " auto md " )

filetype

set

smartindent

indent

on

set

expandtab

set

t a b s t o p=4

set

s o f t t a b s t o p =4

10

set

s h i f t w i d t h =4

11

endif
Pen arian mengabaikan huruf besar atau ke il (in asesensitive).

set

ignore ase

" Do

ase

insensitive

mat hing

BAB 2.

PEMASANGAN

Bila kata yang di ari mengandung huruf besar dan huruf ke il, maka pen arian memperhatikan huruf besar atau ke il ( asesensitive).
1

set

smart ase

" Do s m a r t

ase

mat hing

Aktifkan kedua opsi pen arian di atas, maka pen arian di vim ( menggunakan 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
maka sambutannya seperti ini:

Python

[GCC 4 . 4 . 3

Type

information .

2.6.5

" help " ,

( r265 : 7 9 0 6 3 ,
on

Apr

16

2010 ,

13:57:41)

linux2

" opyright " ,

" redits"

or

" li ense "

for

more

>>>
Mulailah dengan yang sederhana, menampilkan sebuah pesan menggunakan
perintah print.

1
2

>>> p r i n t
Hello

' Hello

World ! '

World !

Gunakan tombol panah atas untuk mengulang perintah sebelumnya, lalu kita oba sedikit salah satu iri pemgrograman berorientasi objek (obje t oriented
programming / OOP).
1

>>> p r i n t

HELLO WORLD!

>>> p r i n t

hello

' Hello
' Hello

World ! ' . u p p e r ( )
World ! ' . l o w e r ( )

world !

'Hello World!' adalah sebuah string, yaitu DATA yang boleh berisi alphanumeri , 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.

BAB 3.

10

HELLO WORLD!

Bingung ?

Lupakan dulu pemrograman berorientasi objek.

Untuk keluar

dari modus interaktif tekan Ctrl-D.

3.1

Variabel dan Tipe Datanya

Selain menggunakan kutip tunggal, string juga dapat dibatasi oleh kutip ganda:
1
2

>>> p r i n t

" H a r i Jum ' a t "

H a r i Jum ' a t
Bila string lebih dari satu baris Anda bisa gunakan kutip tiga kali:

1
2
3

>>> p r i n t

" " "Nama :

...

Alamat :

...

Hobi :

Nama :

Alamat :

Hobi :

Bummi Dwi

Putera

Bogor

Menggambar " " "

Bummi Dwi

Putera

Bogor

Menggambar

Perhatikan tiga buah titik di atas yang berarti sebuah perintah belum berakhir.
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.


Listing 3.1: pegawai.py
1

nama = r a w _ i n p u t ( ' Nama :

a l a m a t = r a w _ i n p u t ( ' Alamat :

h o b i = r a w _ i n p u t ( ' Hobi :

4
5
6

print
print
print

' Nama :

' ,

' Alamat :
' Hobi :

')
')

')

nama
' ,

' ,

alamat

hobi

Setelah disimpan jalankan:


1

python

p e g a w a i . py

Lalu masukkan data seperti yang diminta:


1

Nama :

Alamat :

Bummi Dwi

Hobi :

Putera

Bogor

Menggambar

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.

11

HELLO WORLD!

>>> nama = r a w _ i n p u t ( ' Nama :

Nama :

>>> p r i n t

<t y p e

')

Bummi
t y p e ( nama )

' s t r '>

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

>>> b = 5

>>> p r i n t

a + b

>>> p r i n t

<t y p e

type ( a )

' i n t '>

Variabel a dan b bertipe integer alias bilangan bulat.

Berikut ini untuk

bilangan pe ahan (oat).


1

>>> = 7 . 2

>>> p r i n t

<t y p e

type ( )

' 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.
1

>>> nama =

>>> umur = 2 4

>>> p r i n t

Tra eba k

5
6

File

' Bummi '

nama +
( most

'

"< s t d i n >" ,

TypeError :

usia

re ent
line

annot

' + umur +
all
1,

'

tahun '

last ) :

i n <module>

on atenate

' str '

and

' int '

obje ts

Untuk mengatasinya jadikan variabel umur menjadi string:


1

>>> p r i n t

Bummi

usia

nama +
24

'

usia

' + s t r ( umur ) +

'

tahun '

tahun

Atau dengan ara lain yg lebih mudah diba a:


1

>>> p r i n t

Bummi

usia

'% s
24

u s i a %s

tahun ' % ( nama ,

umur )

tahun

Meski string tidak bisa ditambah dengan integer, namun string bisa dikalikan
dengan integer:
1
2

>>> p r i n t

' ab '

10

a b a b a b a b a b a b ab ab ab ab
Kembali ke le pegawai.py, tidak diperkenankan menulis tidak rapi. Cobalah membuat kesalahan di baris terakhir pada le pegawai.py, yaitu dengan
menambahkan dua spasi sebelum print:

BAB 3.

12

HELLO WORLD!

nama = r a w _ i n p u t ( ' Nama :

a l a m a t = r a w _ i n p u t ( ' Alamat :

h o b i = r a w _ i n p u t ( ' Hobi :

print

' Nama :

print

' Alamat :

print

',

' Hobi :

')
')

')

nama
',

alamat

',

hobi

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
File

print

4
5

p e g a w a i . py

" p e g a w a i . py " ,
' Hobi :

',

line

hobi

^
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 ).
1

nama = r a w _ i n p u t ( ' Nama :

a l a m a t = r a w _ i n p u t ( ' Alamat :

h o b i = r a w _ i n p u t ( ' Hobi :

print

' Nama :

print

' Alamat :

if

',

')
')

')

nama
',

alamat

',

hobi

hobi :
print

' Hobi :

S ript di atas berarti jika hobi diisi maka ditampilkan.

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 :
print

' Hobi :

',

hobi

bisa juga ditulis dengan


1
2

if

hobi
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.

13

HELLO WORLD!

Tipe

False

True (Contoh)

String

'ab '

Integer

Float

1.2

List

[10,20,30

Di tionary

{}

{'nama': 'Bummi', 'alamat': 'Bogor'}

Objek

None

True

Tabel 3.1: Kondisi False di berbagai tipe data

>>> h o b i =

>>> h o b i

3
4
5

' Menggambar '

!=

''

>>> h o b i ==

''

True
False
Lalu obalah variabel hobi kosong.

>>> h o b i =

>>> h o b i

3
4
5

''

!=

''

>>> h o b i ==

''

False
True
Pahami baik-baik perbedaan keduanya. Perhatikan juga penggunaan karakter samadengan dua kali ( == ) yang berarti operasi logika (boolean operation).

>>> k o s o n g = h o b i ==

>>> p r i n t

''

kosong

True
Kembali ke pegawai.py dimana bila hobi tidak diisi maka program akan
memberikan saran. Salinlah menjadi pegawai1.py seperti berikut ini.
Listing 3.2: pegawai1.py

nama = r a w _ i n p u t ( ' Nama :

a l a m a t = r a w _ i n p u t ( ' Alamat :

h o b i = r a w _ i n p u t ( ' Hobi :

4
5
6
7
8
9

print
print
if
print
else
print

' Nama :

' ,

' Alamat :

')
')

')

nama
' ,

alamat

' ,

hobi

hobi :
' Hobi :

' Sebaiknya

hobi

diisi . '

else digunakan untuk kondisi sebaliknya (False).


tambahan ?

Bagaimana jika kondisi

Misalkan jika hobinya menggambar maka pesan untuk hadir di

hari Sabtu ditampilkan.

BAB 3.

14

HELLO WORLD!

Listing 3.3: pegawai2.py


1

nama = r a w _ i n p u t ( ' Nama :

a l a m a t = r a w _ i n p u t ( ' Alamat :

h o b i = r a w _ i n p u t ( ' Hobi :

4
5
6
7
8
9
10
11

print
print
if
print
elif
print
else
print

' Nama :

' ,

' Alamat :

')
')

')

nama
' ,

alamat

h o b i . u p p e r ( ) ==
' Datanglah

'MENGGAMBAR' :
di

pelatihan

gambar

setiap

Sabtu . '

hobi :
' Hobi :

' ,

hobi

' Sebaiknya

hobi

diisi . '

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
2
3
4
5
6
7
8
9
10
11
12

Listing 3.4: pegawai3.py

while
if not
break
True :

nama = r a w _ i n p u t ( ' Nama :

')

nama :

a l a m a t = r a w _ i n p u t ( ' Alamat :
h o b i = r a w _ i n p u t ( ' Hobi :

print
print
if
print
else
print

' Nama :

' ,

' Alamat :

')

')

nama
' ,

alamat

' ,

hobi

hobi :
' Hobi :

' Sebaiknya

hobi

diisi . '

Perhatikan baris pertama yang berarti perulangan tanpa henti. Yang menghentikannya 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:
1. Nama dan alamat harus diisi.
2. Bila selesai satu data pegawai maka program akan menanyakan apakah
akan memasukkan data berikutnya.

BAB 3.

15

HELLO WORLD!

Di sini akan kita ubah sedikit logika while-nya.


Listing 3.5: pegawai4.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

lanjut =

'Y '

while
if not
print
ontinue
if not
print
ontinue
print
print
if
print
else
print
lanjut

!=

'S ' :

nama = r a w _ i n p u t ( ' Nama :

')

nama :

' Nama h a r u s

diisi . '

a l a m a t = r a w _ i n p u t ( ' Alamat :

')

alamat :
' Alamat

harus

h o b i = r a w _ i n p u t ( ' Hobi :
' Nama :

' ,

' Alamat :

diisi . '
')

nama
' ,

alamat

' ,

hobi

hobi :

' Hobi :

' Sebaiknya

lanjut

hobi

diisi . '

= r a w _ i n p u t ( ' Tekan

"S"

jika

selesai :

' ) . upper ( )

ontinue pada baris ke 6 menandakan alur kembali ke while pada baris ke 2.


Perhatikan juga penggunaan raw_input() pada baris terakhir. Karena fungsi
ini mengembalikan nilai string maka kita bisa lanjutkan dengan memanggil
fungsi upper(). Dengan ara ini user diperbolehkan memasukkan dengan s ke il
maupun S besar.
while o ok untuk perulangan yang kondisinya tidak menentu. Bagaimana
bila kita butuh perulangan yang jumlahnya sudah diketahui ? Misalkan etak
angka 1 hingga 5.
1

for

in

[1 ,2 ,3 ,4 ,5:

print

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
2

for

in

print

range ( 5 ) :
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
2

for

in

print

range ( 1 , 6 ) :
i

Karena for merupakan perulangan juga sebagaimana while, maka perintah


break dan ontinue juga berlaku di dalamnya.

Bab 4

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

Sudah dibahas sebelumnya bagaimana menuliskan data bertipe string.


1

>>> nama =

' Agus '

Atau bisa juga menggunakan kutip ganda.


1

>>> nama = Agus


Jika Anda butuh kutip tunggal di dalam string, siasatilah.

>>> h a r i = Jum ' a t


Masih belum yakin apa tipe data variabel nama ? Gunakan type().

>>> t y p e ( nama )

<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 ( +
).
1

>>> p r i n t

Agus

lahir

nama +
hari

'

lahir

hari

' + hari

Jum ' a t

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.
1

>>> p r i n t

Agus

lahir

'% s

lahir

hari

h a r i %s ' % ( nama ,

Jum ' a t

17

hari )

BAB 4.

18

TIPE DATA

Lalu bagaimana menampilkan % itu sendiri di dalam formatting ? Sebutkanlah dua kali.
1
2

>>> p r i n t

' Keuntungan

Keuntungan

4.2

bulan

ini

bulan

ini

meningkat

m e n i n g k a t %d %%' % ( 1 0 )
10 %

Bilangan

Bilangan bulat atau integer atau disingkat int dinyatakan tanpa titik.
1

>>> a = 1 0
a ditambah 2

>>> a + 2
12

1
2

a dikurang 4
1
2

>>> a

6
a dikali 5

1
2

>>> a

50
a dibagi dengan 3

1
2

>>> a

3
Mengapa bukan 3.3333 ?
Pembagian bilangan bulat dengan bilangan bulat menghasilkan bilangan bulat juga. Jika Anda mengharapkan hasil yang lebih rin i maka salah satunya
harus bilangan pe ahan (oat).

1
2

>>> a

3.0

3.3333333333333335
Untuk mendapatkan sisa pembagian (modulus) gunakan tanda persen ( %
).

1
2

>>> a % 3
1
a pangkat 2

1
2

>>> a
100

**

BAB 4.

19

TIPE DATA

4.2.1 Konversi Tipe Data


Konversi dari string menjadi bilangan bulat menggunakan fungsi int().
1
2

>>> i n t ( ' 1 0 ' )


10
int() juga dapat digunakan untuk pembulatan.

1
2

>>> i n t ( 1 0 . 2 )
10
Untuk pembulatan yang mendekati gunakan round().

1
2
3
4

>>> r o u n d ( 1 0 . 4 )
10
>>> r o u n d ( 1 0 . 5 )
11
round() akan membulatkan ke bawah bila pe ahan suatu bilangan lebih ke il
dari 0,5. Sebaliknya ia akan membulatkan ke atas.
Untuk konversi dari string menjadi bilangan pe ahan menggunakan fungsi
oat().

1
2

>>>

float ( '10.5 ')

10.5

4.2.2 Formatting
Menuliskan bilangan ke dalam string bisa menggunakan formatting.
1

>>> a = 3

>>> b = 2

>>> p r i n t

3 + 2 = 5

'% s + %s = %s ' % ( a ,

b,

a+b )

Meski formatting %s bisa digunakan untuk tipe data apa saja, sebaiknya Anda 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

>>> p r i n t

3 + 2 = 5

'%d + %d = %d ' % ( a ,

b,

a+b )

Untuk bilangan pe ahan (oat) gunakan %f.


1

>>> a = 3 . 5

>>> p r i n t

'% f + %f = %f ' % ( a ,

b,

a+b )

3.500000 + 2.000000 = 5.500000


Anda juga bisa mengatur jumlah digit di belakang koma.
1
2

>>> print '%.2f + %.2 f = %.2f ' % (a , b , a +b)


3.50 + 2.00 = 5.50

BAB 4.

20

TIPE DATA

4.2.3 Kalkulator
Membuat kalkulator tidaklah sulit, Anda ukup gunakan eval().

Buatlah le

al .py berikut ini.

1
2
3
4
5

while
if not
break
print

Listing 4.1: al .py

True :

h i t u n g = raw_input ( ' Hitung

')

hitung :

eval ( hitung )

Jalankan.
1

Hitung

python

Hitung

49

Hitung

13

Hitung

a l . py

2+3

7 ** 2

7 + 2

Perhatikan baik-baik. Semua kalimat Python diterjemahkan oleh eval(), baik


kalimat itu mengandung spasi ataupun tidak, eval() sanggup memahaminya.
Mudah bukan?
Perhatikan juga kalimat 7 + 2 * 3 yang menghasilkan nilai 13. Ini artinya
aturan prioritas pada matematika umum berlaku, dimana perkalian lebih dulu
dilakukan ( 2 * 3 ). Barulah hasilnya ( 6 ) ditambahkan dengan 7.
Program di atas akan terus meminta masukkan dari user hingga tombol
Enter saja yang ditekan.

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.
1
2

for

print

in

' Bummi ' :

h ,

hasilnya:
1

Bummi
Perhatikan penggunaan koma pada print yang berarti jangan ganti baris.
Mari kembali ke modus interaktif untuk men oba list.

BAB 4.

21

TIPE DATA

Gambar 4.1: Struktur list

>>> d a t a = [ ' Bummi Dwi

>>> p r i n t

3
4
5

P u t e r a ' , ' Bogor ' , ' Menggambar ' , 2 4

data [ 0

' Bummi Dwi


>>> p r i n t

Putera '
data [ 1

' Bogor '


Tampilkan elemen terakhir:

1
2

>>> p r i n t

data [ 1

24
Elemen kedua dari terakhir:

1
2

>>> p r i n t

data [ 2

' Menggambar '

4.3.1 Pemenggalan
Selain dapat diambil per elemen, juga dapat diambil beberapa elemen sekaligus, ini disebut sebagai pemenggalan (sli ing). Tampilkan elemen pertama dan
kedua:
1
2

>>> p r i n t

data [ 0 : 2

[ ' Bummi Dwi

Putera ' ,

' Bogor '

Atau ukup ditulis tanpa 0:


1
2

>>> p r i n t

data [ : 2

[ ' Bummi Dwi

Putera ' ,

' Bogor '

Tampilkan 3 elemen terakhir:


1

>>> p r i n t

[ ' Bogor ' ,

data [

3:

' Menggambar ' ,

24

Ada baiknya kita pahami ara kerjanya. Pemenggalan list bekerja dengan
batas elemen.
sebagai list.

Gambar 4.1 adalah ontoh string Python yang bisa dianggap

Cermati baik-baik bagaimana bekerja dengan elemen dan batas

elemen (untuk pemenggalan).

BAB 4.

22

TIPE DATA

4.3.2 Keberadaan Elemen


Anda memiliki daftar nama buah yang dapat di ari oleh user.

Setelah user

memasukkan nama buah program akan men arinya dalam list dan memberitahukan hasilnya. Setelah itu program akan kembali menanyakan nama buah
berikutnya. Program berakhir jika user hanya menekan Enter saja, alias tidak
memasukkan apapun. Sekarang buatlah produk.py berikut ini.
Listing 4.2: produk.py
1

d a f t a r = [ ' j e r u k ' , ' mangga ' , ' a p e l ' , ' p i s a n g ' , ' jambu '

while
if not
print
break
if
in
print
else
print

3
4
5
6
7
8
9
10
11

True :

a r i = raw_input ( ' C a r i

buah :

')

ari :

ari

' Selesai '


daftar :

( ' Ditemukan ' )

( ' Tidak

ditemukan ' )

Jalankanlah.
1

Cari

python

Ditemukan

p r o d u k . py

buah :

Cari

Tidak

buah :

Cari

Selesai

mangga
duku

ditemukan
buah :

Keberadaan elemen bisa digunakan sebagai kondisi. Misalkan program Anda


dapat menerima masukan (input parameter) sesaat sebelum dijalankan, sering
disebut sebagai argument. Seperti pada ontoh at.py berikut ini.

1
2

import
print

Listing 4.3: at.py


sys
sys . argv

Jalankanlah.
1

[ ' a t . py '

python

a t . py

Jalankan lagi dengan input parameter.


1

[ ' a t . py ' ,

python

a t . py

/et /hosts

'/ et / hosts '

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.

1
2

23

TIPE DATA

Listing 4.4: at1.py

import

sys

f i l e n a m e = sys . argv [ 1

print

5
6

f = open ( f i l e n a m e )
f . read ( )

f . lose ()
Jalankan.

127.0.0.1

python

a t 1 . py

lo alhost

/et /hosts

127.0.1.1

ompaq

ompaq

4
5

# The

following

lines

are

desirable

for

IPv6

apable

hosts
6

::1

lo alhost

fe00 : : 0

i p 6l o a l n e t

i p 6l o a l h o s t

ff00 ::0

i p 6 m a s t p r e f i x

ff02 ::1

i p 6 a l l n o d e s

10

ff02 ::2

ip6a l l r o u t e r s

11

ff02 ::3

ip6a l l h o s t s

i p 6 l o o p b a k

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

Tra eba k

3
4
5

python
File

a t 1 . py
( most

" a t . py " ,

re ent
line

all
3,

last ) :

i n <module>

f i l e n a m e = sys . argv [ 1
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
2
3
4

import
if not
print

Listing 4.5: at2.py

sys

sys . argv [ 1 : :
( ' Cara

menggunakannya :

sys . argv [ 0 )

sys . exit ()

6
7

f i l e n a m e = sys . argv [ 1

print

9
10

f = open ( f i l e n a m e )
f . read ( )

f . lose ()

p y t h o n %s <nama f i l e > ' %

BAB 4.

24

TIPE DATA

Jalankanlah tanpa input parameter,


1

Cara

python

a t 2 . py

menggunakannya :

python

a t . py <nama f i l e >

Kini program akan menampilkan petunjuk ara menggunakannya. Mari kita


bahas ara kerjanya.
Perhatikan baris ketiga

if not sys.argv[1::
Kalau kita perhatikan lagi isi dari sys.argv pada saat tidak diberikan input
parameter adalah:

[' at.py'
Dengan begitu sys.argv[1: akan bernilai list hampa:

[
Ingatlah mengenai pemenggalan list pada pembahasan sebelumnya. Bila suatu
variabel hampa maka ia bisa dianggap sebagai boolean False, sehingga

if not sys.argv[1::
bisa berarti

if not [:
yang berarti

if not False:
dan ini bisa diartikan menjadi:

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 ?
sys.argv menjadi

[' at.py', '/et /hosts'


Dengan begitu

if not sys.argv[1::
bisa berarti

if not ['/et /hosts':

Nilai

BAB 4.

25

TIPE DATA

Karena ['/et /hosts' adalah list yang berisi (tidak hampa) maka bisa dianggap
sebagai boolean True

if not True:
dan ini berarti juga

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.

4.3.3 Mengubah Elemen


Contoh sebelumnya menjelaskan bagaimana menggunakan list. Kini kita oba
berawal dari list hampa dan mengisinya dengan elemen data. Kembali ke modus
interaktif.
1

>>> d a f t a r =

>>> d a f t a r

[
Tambahkan mangga.

>>> d a f t a r . append ( ' mangga ' )

>>> d a f t a r

[ ' mangga '


Bisa juga dengan ara lain.

>>> d a f t a r += [ ' p i s a n g '

>>> d a f t a r

[ ' mangga ' ,

' pisang '

Kita akan ubah elemen kedua (index ke 1) dari pisang menjadi jeruk.
1

>>> d a f t a r [ 1

>>> d a f t a r

[ ' mangga ' ,

' jeruk '

' jeruk '

Selanjutnya mangga dihapus yang berarti elemen pertama atau index ke 0.


1

>>> d e l

>>> d a f t a r

daftar [ 0

[ ' jeruk '

BAB 4.

4.4

26

TIPE DATA

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 lainnya. Sekarang buatlah s ript berikut ini.
Listing 4.6: produk1.py
1

daftar = {

2:

' jeruk ' ,

7:

' mangga ' ,

4:

' pisang ' ,

3:

' jambu ' ,

9:

' apel ' ,

print

daftar

Jalankan.
1

{9:

python

p r o d u k 1 . py

' apel ' ,

2:

' jeruk ' ,

3:

' jambu ' ,

4:

' pisang ' ,

7:

'

mangga ' }
Perhatikan urutan pada sour e, dan bandingkan urutan buah saat ditampilkan. Begitulah di tionary, dia memang tidak memperhatikan urutan. Inilah 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 (value). Karena itu di tionary sering disebut sebagai tipe data dengan formasi key
value.
Sekarang kita buat pen arian berdasarkan kode barang.
Listing 4.7: produk2.py
1

daftar = {

2:

' jeruk ' ,

7:

' mangga ' ,

4:

' pisang ' ,

3:

' jambu ' ,

9:

' apel ' ,

8
9
10
11
12
13

while
if not
print
break
True :

k e y = r a w _ i n p u t ( ' Kode
key :
' Selesai '

barang :

')

BAB 4.

if
in
print
else
print

14

key

15
16

27

TIPE DATA

daftar :
d a f t a r [ key

17

' Kode

barang ' ,

key ,

' tidak

ditemukan '

Cobalah.
1

Kode

python

barang :

p r o d u k 2 . py

Kode

barang

Kode

barang :

Kode

barang

Kode

barang :

Selesai

5
5

tidak

ditemukan

tidak

ditemukan

9
9

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

key = raw_input('Kode barang: ')


juga bertipe string. Lalu

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

print 'Kode barang', key, 'tidak ditemukan'


menjadi

print 'Kode barang', [key, 'tidak ditemukan'


Coba jalankan lagi.
1

Kode

python

barang :

Kode

barang

tidak

Kode

Selesai

p r o d u k 2 . py
9
[ '9 '

ditemukan
barang :

Dengan memberikan kurung siku pada variabel maka akan tampak bahwa
key adalah string.

Terlihat adanya kutip tunggal pada '9'.

mengubah key agar bertipe integer ? Gunakan fungsi int().

Lalu bagaimana

BAB 4.

28

TIPE DATA

Listing 4.8: produk3.py


1

daftar = {

2:

' jeruk ' ,

7:

' mangga ' ,

4:

' pisang ' ,

3:

' jambu ' ,

9:

' apel ' ,

8
9
10
11
12
13
14
15
16
17
18

while
if not
print
break
if
in
print
else
print
True :

k e y = r a w _ i n p u t ( ' Kode

barang :

')

key :
' Selesai '

key = i n t ( key )
key

daftar :
d a f t a r [ key

' Kode

barang ' ,

key ,

' tidak

ditemukan '

Jalankan lagi.
1

Kode

python

barang :

Kode

barang

Kode

barang :

apel

Kode

Selesai

p r o d u k 3 . py
5
[5

tidak

ditemukan

barang :

Resapi kembali mengenai tipe data ini karena akan sering dijumpai nanti.

4.5

Waktu

Modul time digunakan untuk penanganan waktu. Kita kembali ke modus interaktif dulu untuk memudahkan latihan.
1

>>> i m p o r t

>>> t = t i m e . l o a l t i m e ( )

>>> t

time

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 ,
=232 ,

tm_se =47 , tm_wday=4 , tm_yday

t m _ i s d s t =0)

Fungsi time.lo altime() digunakan untuk mendapatkan waktu saat ini. Perhatikan variabel t di atas. Jika Anda ingin mengambil tahunnya:
1
2

>>> t . tm_year
2010

BAB 4.

29

TIPE DATA

atau bulannya
1
2

>>> t . tm_mon
8
atau harinya

1
2

>>> t . tm_mday
20
dan seterusnya hingga jam, menit, dan detiknya, ada di sana.
Waktu juga bisa diwujudkan dalam bilangan pe ahan (oat), sering disebut
sebagai epo h atau Unix time.

1
2

>>> t i m e . t i m e ( )
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
2

>>> t i m e . l o a l t i m e ( 0 )
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)
Epo h 0 berarti 1 Januari 1970. Lalu mengapa tm_hour menunjukkan angka
7 ?

Ini terkait dengan zona waktu (timezone) pada komputer yang berarti

wilayah Jakarta (+7). Jika komputer Anda diset pada zona waktu Bali maka
nilai tm_hour menjadi 8.
Untuk mendapatkan epo h pada tanggal 17 Agustus 2010 maka bisa gunakan
time.mktime():
1
2

>>> t i m e . mktime ( ( 2 0 1 0 , 8 , 1 7 , 0 , 0 , 0 , 0 , 0 , 0 ) )
1281978000.0
Dengan epo h kita bisa mendapatkan jumlah hari sejak 1 Agustus 2010
hingga 17 Agustus 2010.

>>> a w a l = t i m e . mktime ( ( 2 0 1 0 , 8 , 1 , 0 , 0 , 0 , 0 , 0 , 0 ) )

>>> a k h i r = t i m e . mktime ( ( 2 0 1 0 , 8 , 1 7 , 0 , 0 , 0 , 0 , 0 , 0 ) )

>>> a k h i r

1382400.0

awal

Itu adalah jumlah detiknya. Untuk mendapatkan hari kita perlu mengolahnya kembali.
1
2

>>> ( a k h i r

awal )

24

16.0
Sehingga diperoleh 16 hari.

60

60

BAB 4.

30

TIPE DATA

Modul datetime
Menghitung hari lebih mudah menggunakan modul datetime.
1

>>> f r o m

>>> a w a l = d a t e ( 2 0 1 0 , 8 , 1 )

>>> a k h i r = d a t e ( 2 0 1 0 , 8 , 1 7 )

>>> d = a k h i r

>>> d . d a y s

datetime

import

date

awal

16
Dengan modul ini kita juga dapat menghitung jumlah detik sejak 16 Agustus
2010 jam 22:00 hingga 17 Agustus 2010 jam 10:00.

>>> f r o m

>>> a w a l = d a t e t i m e ( 2 0 1 0 , 8 , 1 6 , 2 2 , 0 , 0 )

>>> a k h i r = d a t e t i m e ( 2 0 1 0 , 8 , 1 7 , 1 0 , 0 , 0 )

>>> d = a k h i r

>>> d . s e o n d s

datetime

import

datetime

awal

43200
Untuk mendapatkan jumlah jamnya:

1
2

>>> d . s e o n d s
12

60

60

Bab 5

Modularitas
Mari kita buat program yang menghitung nilai faktorial.

Apa itu faktorial ?

Berikut ini ontohnya:

5!
4!
3!
2!
1!
0!
-1!

=
=
=
=
=
=
=

5
4
3
2
1
1
1

*
*
*
*

4
3
2
1

*
*
*
=

3 * 2 * 1 = 120
2 * 1 = 24
1 = 6
2

Dengan demikian rumus faktorial memiliki ketentuan:


1. Jika n < 2 maka n! = 1
2. n! = n * (n-1)!
Selanjutnya kita akan buat program yang akan menanyakan nilai n dan menampilkan
nilai faktorial-nya.

1
2
3
4
5
6
7
8
9
10
11
12
13

print
while
if not
break
if
else
for in
*
print

Listing 5.1: faktorial1.py

' Menghitung

nilai

faktorial '

True :

n = raw_input ( ' n =

')

n:

n = int (n)
n < 2:

f = 1
:

f = 1
i

f = f

'%d !

r a n g e ( 1 , n+1) :
i

= %d ' % ( n ,

f)
31

BAB 5.

32

MODULARITAS

Jalankan.
1

Menghitung

python

n = 2

2! = 2

n = 3

3! = 6

n = 4

4 ! = 24

n =

10

f a k t o r i a l 1 . py
nilai

faktorial

$
Selesai sudah.

Berikutnya Anda diminta membuatnya dalam lingkungan

gras (graphi al user interfa e / GUI). Tentu saja tidak ada lagi yang namanya
raw_input() dan print, karena ia digunakan untuk lingkungan teks ( onsole).
Juga tidak ada lagi while karena GUI sudah mengatur perulangannya.
Lalu apa yang diambil untuk mengambil sour e faktorial ?
saja yang perlu di- opy-paste di sour e GUI nanti.

Baris 6 - 12

Anda juga harus menye-

suaikan variabel n yang menjadi masukannya, karena n tidak lagi berasal dari
raw_input() melainkan dari komponen GUI.
Di sini mulai terasa sour e faktorial di atas tidak modular karena menyulitkan
opy-paste. Kesulitan yang dimaksud adalah sour e faktorial menyatu dengan
sour e yang mengurus tampilan. Faktorial adalah ontoh sederhana, bagaimana
kalau nanti Anda diminta membuat rumus lainnya yang jauh lebih rumit ?

5.1

Membuat Fungsi

Sudah saatnya Anda mengenal pembuatan fungsi. Dengannya Anda pisahkan


urusan menghitung nilai faktorial dengan urusan input dan output tampilannya.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

def
if

Listing 5.2: faktoria2l.py


f akt ori al (n) :
n < 2:

return
for in
*
return

f = 1
i

f = f

r a n g e ( 1 , n+1) :
i

print
while
if not
break

' Menghitung

nilai

True :

n = raw_input ( ' n =
n:

')

faktorial '

BAB 5.

33

MODULARITAS

15

n = int (n)

16

print

h a s i l = f a k t o r i a l (n)

17

'%d !

= %d ' % ( n ,

hasil )

Jalankan.
1

Menghitung

python

n = 5

5 ! = 120

n = 2

2! = 2

n = 1

1! = 1

n =

10

1!

= 1

11

n =

f a k t o r i a l 2 . py
nilai

faktorial

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.

5.2

Membuat Modul

Copy-paste sour e seperti itu tentu saja lebih sulit ketimbang opy-paste lenya. Oleh karena itu Anda perlu membuat sour e itu menjadi modul faktorial
yang berarti namanya menjadi faktorial.py sehingga program lain yang membutuhkannya ukup menggunakannya seperti ini ( ontoh):
1

from

n = 5

faktorial

print

import

faktorial

f a k t o r i a l (n)

Sekarang buatlah faktorial.py.

1
2
3
4
5
6

def
if
return
for in
*
return

Listing 5.3: faktorial.py

faktorial (a) :
a < 2:
i

a = a

1
range ( 1 , a ) :
i

Lalu buatlah obafaktorial.py yang menggunakan modul faktorial ini.

from

Listing 5.4: obafaktorial.py

faktorial

import

faktorial

BAB 5.

2
3
4
5
6
7
8

34

MODULARITAS

print
while
if not
break

' Menghitung

nilai

faktorial '

True :

n = raw_input ( ' n =

')

n:

n = int (n)

h a s i l = f a k t o r i a l (n)

print

10

'%d !

= %d ' % ( n ,

hasil )

Jalankan.
1

Menghitung

python

n = 5

5 ! = 120

n = 2

2! = 2

n =

o b a f a k t o r i a l . py
Nilai

Faktorial

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

from faktorial import faktorial


sour e uji oba tersebut tidak dijalankan. Silahkan ubah faktorial.py menjadi
berikut ini.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

def
if
return
for in
*
return
if
print
while
if not
break

Listing 5.5: faktorial.py

faktorial (a) :
a < 2:
i

a = a

1
range ( 1 , a ) :
i

__name__ ==

'__main__ ' :

' Menghitung

nilai

True :

n = raw_input ( ' n =
n:

n = int (n)

')

faktorial '

BAB 5.

15

hasil =

print

16

35

MODULARITAS

fakt orial (n)

'%d ! = %d ' % ( n ,

hasil )

Perhatikan bahwa __name__ adalah name yang diawali dan diakhiri oleh
dua unders ore. Begitu juga dengan __main__. Kemudian jalankan.
1

Menghitung

python

n = 3

3! = 6

n = 4

4 ! = 24

n =

f a k t o r i a l . py
nilai

faktorial

Jadi perubahannya adalah pada

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

5.3

o b a f a k t o r i a l . py

Sear h Path

Meng- opy faktorial.py ke berbagai direktori program yang membutuhkan tentu


saja merepotkan. Apalagi bila ada perubahan sour e pada faktorial.py, maka
Anda harus menyebarkannya lagi.
Ada banyak direktori dimana Python akan men ari modul yang dipanggil.

Untuk mengetahui direktori mana saja yang terdaftar gunakan variabel

sys.path. Masuklah ke modus interaktif untuk melihatnya.


1

>>> i m p o r t

>>> s y s . p a t h

sys

[ ' ' ,

' / u s r / l i b / python2 . 6 ' ,

' / u s r / l i b / p y t h o n 2 . 6 / p l a t l i n u x 2 ' ,

' / u s r / l i b / python2 . 6 / l i b

11

t k ' ,
o l d ' ,
' / u s r / l i b / p y t h o n 2 . 6 / l i b d y n l o a d ' ,
' / 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 ' ,
' / 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 ' ,
' / 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

14

' / u s r / l i b / pymodules / python2 . 6 / gtk

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 '

7
8
9
10

' / u s r / l i b / python2 . 6 / l i b

2.0 ' ,
2.0 ' ,

BAB 5.

36

MODULARITAS

Pertama kali Python akan men ari di direktori dimana program utama berada. 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

/usr/lo al/lib/python2.6/dist-pa kages


Anda bisa menyalinnya menggunakan perintah
1

sudo

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
Supaya lebih yakin pindahkan sekalian.
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

>>> s y s . p a t h . append ( ' / home / s u g i a n a / l i b ' )

sys

>>> f r o m

faktorial

import

faktorial

Bab 6

Fungsi
6.1

Memanggil Dirinya Sendiri

Fungsi faktorial() sudah bekerja dengan baik. Tapi mungkin sour e-nya terlalu
panjang. Cobalah ubah menjadi seperti di bawah ini pada faktorial.py.
1
2

def
if

3
4

faktorial (a) :
a < 2:
return

return

f a k t o r i a l ( a 1)

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.

6.2

Format Uang

Untuk menampilkan uang biasanya ada pemisah ribuannya. Untuk Indonesia


pemisah ribuan adalah titik, sedangkan pemisah pe ahan adalah koma. Untuk
kebutuhan tersebut kita bisa gunakan modul lo ale.
1

>>> i m p o r t

>>>

3
4
5

lo ale

l o a l e . s e t l o a l e ( l o a l e . LC_ALL, ' id_ID . UTF 8 ' )

' id_ID . UTF8 '


>>>

l o a l e . format ( '%.2 f ' ,

10000 ,

True )

'10.000 ,00 '


Jika pe ahannya tidak ingin ditampilkan:

1
2

>>>

l o a l e . format ( '%.0 f ' ,

10000 ,

True )

'10.000 '
Namun jika saat setlo ale Anda menjumpai pesan kesalahan seperti ini:

37

BAB 6.

38

FUNGSI

Tra eba k

( most

re ent
line

all
1,

last ) :

File

"< s t d i n >" ,

i n <module>

File

" / u s r / l i b / p y t h o n 2 . 6 / l o a l e . py " ,

line

513 ,

in

setlo ale
4
5

return

_ s e t l o a l e ( ategory ,

l o a l e . Error :

unsupported

lo ale

lo ale )
setting

Berarti Anda perlu memasang format id_ID.UTF-8 pada sistem. Keluarlah


dari modus interaktif dan jalankan:
1

Generating

3
4

sudo

l o a l e g e n

id_ID . UTF 8 . . .
Generation

id_ID . UTF8

lo ales . . .
upt o d a t e

omplete .

Kalau sudah obalah kembali ontoh pemisah ribuan di atas.


Kini saatnya membuat fungsi untuk menampilkan nilai uang ini. Kita namakan dengan uang(). Fungsi ini akan menerima dua masukan:
1. Nilai uang yang akan ditampilkan
2. Jumlah digit pe ahan yang akan ditampilkan, default-nya adalah 2 digit
pe ahan.
Karena uang() adalah fungsi umum yang akan banyak digunakan di berbagai
program, ada baiknya kita simpan sebagai modul bernama uang.py.

1
2

import

Listing 6.1: uang.py


lo ale

l o a l e . s e t l o a l e ( l o a l e . LC_ALL, ' id_ID . UTF8 ' )

3
4
5
6
7
8
9
10

def
return

uang ( n i l a i ,

if

11
12

__name__ ==

print
print
print

p e a h a n =2) :

l o a l e . f o r m a t ( '%%.%d f ' % p e a h a n ,

'__main__ ' :

uang ( 1 0 0 0 0 )
uang ( 1 0 0 0 0 . 3 )
uang ( 1 0 0 0 0 . 5 , 0 )

Cobalah.
1

10.000 ,00

python

10.000 ,30

10.000

uang . py

Perhatikan bagian

'%%.%df' % pe ahan

nilai ,

True )

BAB 6.

39

FUNGSI

Itu adalah formatting seperti yang dijelaskan di halaman 17.


Butuh fungsi yang lebih erdas ? Misalkan dengan sifat seperti ini:
1. Jika pe ahan tidak disebutkan maka modus otomatis berlaku. Otomatis
yang dimaksud adalah bila tipe data variabel nilai adalah bilangan bulat
(integer) maka pe ahan tidak ditampilkan. Selain kondisi itu berarti dianggap bilangan pe ahan (oat) maka pe ahan ditampilkan sebanyak 2
digit.
2. Selain kondisi di atas maka nilai uang ditampilkan seperti biasa sesuai
jumlah pe ahan yang disebutkan.
Masih di uang.py.

1
2

Listing 6.2: uang.py

import

lo ale

l o a l e . s e t l o a l e ( l o a l e . LC_ALL, ' id_ID . UTF8 ' )

3
4
5
6
7

def
if

12

16
17

p e a h a n=None ) :
None :

t y p e ( n i l a i ) == t y p e ( 0 ) :
:

pe ahan = 2

11

15

is

pe ahan = 0

10

14

pe ahan

if
else
return

13

uang ( n i l a i ,

if

l o a l e . f o r m a t ( '%%.%d f ' % p e a h a n ,

__name__ ==

print
print
print

nilai ,

True )

'__main__ ' :

uang ( 1 0 0 0 0 )
uang ( 1 0 0 0 0 . 3 )
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.

40

FUNGSI

2. Bila variabel tanda tidak diisi maka mata uang diambil dari sistem, menggunakan module lo ale.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

Listing 6.3: uang.py

import
from

lo ale

l o a l e . s e t l o a l e ( l o a l e . LC_ALL, ' id_ID . UTF8 ' )


types

def
if

import

ribu ( n i l a i ,

is

pe ahan

if
else
return
def
if
return

IntType

p e a h a n=None ) :
None :

t y p e ( n i l a i ) == I n t T y p e :

pe ahan = 0
:

pe ahan = 2
l o a l e . f o r m a t ( '%%.%d f ' % p e a h a n ,

uang ( n i l a i ,
tanda

is

p e a h a n=None ,

nilai ,

True )

t a n d a=None ) :

None :

tanda = l o a l e . l o a l e o n v ( ) [ ' urren y_symbol '

if

'%s%s ' % ( t a n d a ,

__name__ ==

print
print
print
print
print
print

ribu ( n i l a i ,

pe ahan ) )

'__main__ ' :

ribu (10000)
ribu (10000.3)
ribu (10000.5 ,

4)

uang ( 1 0 0 0 0 . 7 )
uang ( 1 0 0 0 0 . 7 ,

2,

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 berjalan baik itu.

Sehingga bila ada kekeliruan pada algoritma di uang(), area

pen arian kesalahan bisa diminimalisir.


Perhatikan juga baris terakhir,

print uang(10000.7, tanda='$')


dimana kita melewatkan variabel kedua, yaitu pe ahan pada fungsi uang(),

def uang(nilai, pe ahan=None, tanda=None):


Python tidak mempermasalahkan variabel pe ahan dilewatkan, karena variabel
ini telah diberi nilai default yaitu None.

BAB 6.

41

FUNGSI

Karena modul uang ini merupakan modul umum yang bisa digunakan oleh
banyak aplikasi, maka letakkanlah uang.py di /usr/lo al/lib/python2.6/distpa kages agar bisa digunakan oleh program lainnya. Lalu uji keberadaannya di
modus interaktif.
1

>>> f r o m

>>> uang ( 1 0 0 0 0 )

'10.000 '

uang

import

uang

Bab 7

Database
Database atau penyimpan data biasa digunakan untuk aplikasi bisnis seperti
kasir (point of sales), a ounting, payroll, dsb.
Pasanglah
1

sudo

a p t g e t

install

postgresql

Superuser di PostgreSQL adalah postgres.

Nama ini ter antum di sistem

Linux maupun di sistem PostgreSQL itu sendiri. Pas a pemasangan user postgres tidak memiliki password. Jadi gunakanlah sudo:
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

Enter

reateuser

password

ilham

Enter

it

Shall

the

new

role

be

Shall

the

new

role

be

allowed

to

reate

databases?

the

new

role

be

allowed

to

reate

more new

for

new

role :

again :
superuser?

( y /n )

n
( y/n )

n
6

Shall

y /n )

roles?

Isilah password dengan 1234. Saat diketik password tidak akan ditampilkan.
Selebihnya user ilham ini tidak dizinkan sebagai superuser, tidak diizinkan membuat database, dan tidak diizinkan membuat user.
Untuk menghapusnya:
1

dropuser

ilham
42

BAB 7.

43

DATABASE

Selanjutnya membuat database:


1

reatedb

ilham

totalindo

Ini artinya kita membuat database bernama totalindo yang dimiliki oleh user
ilham. Untuk menghapusnya:
1

dropdb

totalindo

Untuk melihat daftar database bisa menggunakan psql:


1

psql

psql
(8.4.4)

Type

" help "

for

help .

4
5

p o s t g r e s=# \ l

List

7
8
9
10
11
12
13

of

databases

Name

Owner

En oding

Collation

++++
postgres
| p o s t g r e s | UTF8
| id_ID . UTF8 |
t e m p l a t e 0 | p o s t g r e s | UTF8
| id_ID . UTF8 |
t e m p l a t e 1 | p o s t g r e s | UTF8
| id_ID . UTF8 |
t o t a l i n d o | ilham
| UTF8
| id_ID . UTF8 |
(4

rows )

14
15

p o s t g r e s=#
Untuk keluar gunakan \q atau tekan Ctrl-D:

p o s t g r e s=# \ q

postgres

whoami

Anda masih sebagai user postgres, keluarlah dengan perintah logout atau
tekan Ctrl-D:
1

# whoami

logout

root
Kini Anda sebagai root, keluarlah lagi dengan perintah logout agar kembali
sebagai user biasa:

# logout

sugiana

whoami

Sekarang kita login ke database totalindo sebagai user ilham:


1

Password

psql

psql

SSL

ilham
for

totalindo

user

lo alhost

ilham :

(8.4.4)
onne tion

( ipher :

DHERSAAES256SHA,

bits :

256)

BAB 7.

Type

44

DATABASE

" help "

for

help .

6
7

t o t a l i n d o=>
Perhatikan di sini kita menggunakan option yang lengkap di psql, padahal
pada saat sebagai user postgres kita ukup mengetikkan psql saja. Apa bedanya
?
psql saja tanpa option apapun berarti:
1. Usernya sesuai user Linux.
2. Nama database sesuai nama user.
3. Koneksi melalui jalur UNIX so ket, tidak melalui network.

7.1

Tabel

Panduan membuat tabel:


1. Harus memiliki PRIMARY KEY, yaitu sebuah / beberapa eld yang menjadi 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.
Mulailah membuat tabel pegawai di psql menggunakan perintah CREATE TABLE.
1

t o t a l i n d o=> CREATE TABLE p e g a w a i (

t o t a l i n d o (>

t o t a l i n d o (> nama

t o t a l i n d o (>

t o t a l i n d o (> PRIMARY KEY( i d )

6
7

t o t a l i n d o (>

id

serial

t g l _ l a h i r DATE NOT NULL,


) ;

NOTICE : CREATE TABLE


pegawai_id_seq "

will

for

reate

serial

impli it

olumn

" p e g a w a i _ p ke y"

t o t a l i n d o=>
Perhatikan prompt

totalindo=>
dan bedakan dengan prompt

totalindo(>

for

table

sequen e

"

" pegawai . i d "

NOTICE : CREATE TABLE / PRIMARY KEY w i l l


index

NOT NULL,

v a r h a r ( 3 0 ) NOT NULL,

reate

impli it

" p e g a w a i " CREATE TABLE

BAB 7.

45

DATABASE

yang bermakna prompt itu kelanjutan dari prompt sebelumnya. Penulisan

CREATE TABLE pegawai(


yang diikuti dengan penekanan tombol Enter membuat prompt memberitahukan
Anda bahwa kurung buka masih aktif dan membutuhkan kurung tutup sebelum
diakhiri dengan titik koma.
Perintah dalam SQL (stru tured query language) sebenarnya tidak memperhatikan huruf besar / ke il (in asesensitive). Anda boleh menuliskan

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
3
4
5
6

List
S hema

of

relations

Name

Type

Owner

+++
publi
(1

pegawai

table

ilham

row )

7
8

t o t a l i n d o=>

Perintah yang diawali ba kslash ( \ ) adalah perintah program psql,


bukan jenis query seperti CREATE TABLE, SELECT, dst.
Lalu lihat struktur tabelnya menggunakan perintah \d diikuti nama tabel.
1

t o t a l i n d o=> \d

2
3

pegawai

Table
Column

" p u b l i . pegawai "

Type

|
Modifiers

4
5

++
id

integer

not

null

n e x t v a l ( ' pegawai_id_seq ' : : r e g l a s s )


6

nama

hara ter

tgl_lahir

date

8
9

not

null

not

null

Indexes :
" p e g a w a i _ p k ey" PRIMARY KEY,

10
11

varying (30)

t o t a l i n d o=>

btree

( id )

default

BAB 7.

46

DATABASE

Perhatikan kolom / eld id yang bertipe integer, padahal sebelumnya kita


tulis bertipe serial. Mengapa demikian ?
Tipe serial hanyalah ara epat untuk membuat sebuah eld menjadi autoin rement (nomor urut).

Jadi pendenisian suatu eld menjadi serial akan

membuat:
1. Tipenya menjadi integer (bilangan bulat).
2. Memiliki default value nomor urut berikutnya.

Nomor urut berikutnya

tersimpan dalam sebuah sequen e.


Apa itu sequen e ?

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 serial. Data pada sequen e bisa dilihat sebagaimana tabel menggunakan perintah
SELECT.
1
2
3
4

t o t a l i n d o=> SELECT
sequen e_name

FROM p e g a w a i _ i d _ s e q

last_value

is_ alled

;
|

+++
pegawai_id_seq

5
6

(1

row )
Sekarang kita lihat isi tabel pegawai.

1
2
3
4

t o t a l i n d o=> SELECT
id

nama

FROM p e g a w a i ;

tgl_lahir

++
(0

rows )
Tampak tabel pegawai masih kosong, mari tambah datanya.

t o t a l i n d o=> INSERT INTO p e g a w a i ( nama , t g l _ l a h i r )

t o t a l i n d o > VALUES ( ' Bummi Dwi

INSERT 0

Putera ' , '1985 8 17 ') ;

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 kelanjutan 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.

47

DATABASE

t o t a l i n d o=> INSERT INT

t o t a l i n d o > ;

ERROR:

syntax

LINE

INSERT INT

1:

5
6

error

p e g a w a i ( nama , t g l _ l a h i r )

at

or

near

"INT"

p e g a w a i ( nama , t g l _ l a h i r )

^
t o t a l i n d o=>
Untuk mengulangi perintah sebelumnya tekan tombol panah atas.
Kembali ke tabel pegawai yang sudah kita isi dengan perintah INSERT.
Sekarang lihat hasilnya.

1
2
3
4
5

t o t a l i n d o=> SELECT
id

FROM p e g a w a i ;

nama

tgl_lahir

++
1 | Bummi Dwi P u t e r a | 1985 08 17
(1

row )
Perhatikan saat INSERT tadi eld id tidak disertakan, namun perintah SE-

LECT memperlihatkan bahwa eld id terisi dengan angka 1. Inilah yang disebut dengan eld autoin rement.

Lalu apa yang terjadi dengan sequen e pe-

gawai_id_seq ?
1
2
3
4

t o t a l i n d o=> SELECT
sequen e_name

FROM p e g a w a i _ i d _ s e q

last_value

is_ alled

++
pegawai_id_seq

5
6

(1

row )
Bandingkan dengan nilai-nilai pegawai_id_seq pada SELECT sebelum IN-

SERT. Yang perlu diperhatikan adalah eld is_ alled dimana sebelumnya f
(False) kini menjadi t (True).

Ini artinya sequen e sudah digunakan agar

nextval() berikutnya tahu bahwa nilai berikutnya menghasilkan last_value + 1


= 2.
Sekarang lanjut dengan pegawai berikutnya.
1

t o t a l i n d o=> INSERT INTO p e g a w a i ( nama , t g l _ l a h i r )

t o t a l i n d o > VALUES ( ' A r i e f

INSERT 0

t o t a l i n d o=> SELECT

5
6
7
8
9

id

S e t i a d i ' , '1972 5 2 ') ;

nama

FROM p e g a w a i ;
|

tgl_lahir

++
1 | Bummi Dwi P u t e r a | 1985 08 17
2 | Arief Setiadi
| 1972 05 02
(2

rows )
Perhatikan kembali eld id yang terisi dengan angka 2, dan lihat juga pe-

gawai_id_seq.
1

t o t a l i n d o=> SELECT

FROM p e g a w a i _ i d _ s e q

BAB 7.

2
3

48

DATABASE

sequen e_name

last_value

is_ alled

+++

pegawai_id_seq

5
6

(1

row )
Kini last_value menjadi 2, sehingga nextval() berikutnya last_value + 1 =

3. Mudah-mudahan bisa dipahami.


Mengenai eld tgl_lahir, bolehkah diisi menggunakan format Indonesia yaitu
dengan urutan tanggal-bulan-tahun ?
Jawabannya boleh, hanya ada yang perlu diperhatikan pada kongurasi
PostgreSQL, yaitu pada le

/et /postgresql/8.4/main/postgresql. onf


Coba lihat dengan text editor.
1

sudo

nano

/ e t / p o s t g r e s q l / 8 . 4 / main / p o s t g r e s q l . o n f

Carilah kata datestyle.

datestyle = 'iso, dmy'


Jika sudah tampak dmy seperti di atas maka Anda diizinkan mengisi eld tanggal dengan format tanggal-bulan-tahun. Namun jika Anda mendapati isinya

datestyle = 'iso, mdy'


maka ubahlah mdy menjadi dmy, simpan, logout semua psql, dan restart PostgreSQL.
1

sudo

/ e t / i n i t . d/ p o s t g r e s q l

8.4

restart

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.
1

t o t a l i n d o=> INSERT INTO p e g a w a i ( nama , t g l _ l a h i r )

t o t a l i n d o > VALUES ( ' Ce ep

INSERT 0

t o t a l i n d o=> SELECT

5
6
7
8
9
10

id

1
nama

Zahrudin ' , '1 6 1972 ') ;

FROM p e g a w a i ;
|

tgl_lahir

++
1 | Bummi Dwi P u t e r a | 1985 08 17
2 | Arief Setiadi
| 1972 05 02
3 | Ce ep Z a h r u d i n
| 1972 06 01
(3

rows )
Agar tampil urut sesuai abjad gunakan ORDER BY.

BAB 7.

1
2
3
4
5
6
7

t o t a l i n d o=> SELECT
id

49

DATABASE

FROM p e g a w a i ORDER BY nama ;

nama

tgl_lahir

++
2 | Arief Setiadi
| 1972 05 02
1 | Bummi Dwi P u t e r a | 1985 08 17
3 | Ce ep Z a h r u d i n
| 1972 06 01
(3

rows )
Gunakan WHERE untuk mendapatkan re ord tertentu.

1
2
3
4
5

t o t a l i n d o=> SELECT
id

FROM p e g a w a i WHERE i d = 1 ;

nama

tgl_lahir

++
1 | Bummi Dwi P u t e r a | 1985 08 17
(1

row )
Tampilkan pegawai yang lahir di tahun 1972 dan diurutkan mulai yang ter-

tua.

t o t a l i n d o=> SELECT

t o t a l i n d o > WHERE d a t e _ p a r t ( ' y e a r ' ,

t o t a l i n d o > ORDER BY t g l _ l a h i r ;

4
5
6
7
8

id

nama

FROM p e g a w a i

t g l _ l a h i r ) = 1972

tgl_lahir

++
2 | Arief Setiadi
| 1972 05 02
3 | Ce ep Z a h r u d i n | 1972 06 01
(2

rows )
Gunakan DESC pada ORDER BY jika ingin diurut mulai yang termuda.

Tekan tombol panah atas untuk mengulang perintah sebelumnya dan tambahkan DESC.
1

t o t a l i n d o=> SELECT

FROM p e g a w a i

WHERE d a t e _ p a r t ( ' y e a r ' ,

ORDER BY t g l _ l a h i r

4
5
6
7
8

id

nama

t g l _ l a h i r ) = 1972

DESC ;
|

tgl_lahir

++
3 | Ce ep Z a h r u d i n | 1972 06 01
2 | Arief Setiadi
| 1972 05 02
(2

rows )

7.1.2 Mengubah Struktur


Pegawai sebelumnya tampak sebagai laki-laki, terlihat dari namanya. Cobalah
untuk memasukkan nama perempuan.
1

t o t a l i n d o=> INSERT INTO p e g a w a i ( nama , t g l _ l a h i r )

t o t a l i n d o > VALUES ( ' N i t a

INSERT 0

Pandria ' , '19 9 1976 ') ;

BAB 7.

50

DATABASE

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 membutuhkan perintah ALTER TABLE di sini.
1

t o t a l i n d o=> ALTER TABLE p e g a w a i ADD p r i a

b o o l e a n NOT NULL

DEFAULT t r u e ;
2

ALTER TABLE
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.

1
2
3
4
5
6
7
8

t o t a l i n d o=> SELECT
id

nama

FROM p e g a w a i ORDER BY nama ;


|

tgl_lahir

pria

+++
2 | Arief Setiadi
| 1972 05 02 | t
1 | Bummi Dwi P u t e r a | 1985 08 17 | t
3 | Ce ep Z a h r u d i n
| 1972 06 01 | t
4 | Nita Pandria
| 1976 09 19 | t
(4

rows )
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.
1
2
3
4
5
6
7
8
9
10

t o t a l i n d o=> UPDATE p e g a w a i SET

p r i a = F a l s e WHERE i d = 4 ;

UPDATE 1
t o t a l i n d o=> SELECT
id

nama

FROM p e g a w a i ORDER BY nama ;


|

tgl_lahir

pria

+++
2 | Arief Setiadi
| 1972 05 02 | t
1 | Bummi Dwi P u t e r a | 1985 08 17 | t
3 | Ce ep Z a h r u d i n
| 1972 06 01 | t
4 | Nita Pandria
| 1976 09 19 | f
(4

rows )
Kita sudah membuat re ord dengan INSERT, menampilkannya dengan SE-

LECT, dan mengubahnya dengan UPDATE. Kini kita oba untuk menghapusnya dengan DELETE FROM yaitu pegawai dengan id 2.
1
2
3
4
5

t o t a l i n d o=> DELETE FROM p e g a w a i WHERE i d = 2 ;


DELETE 1
t o t a l i n d o=> SELECT
id

nama

FROM p e g a w a i ORDER BY nama ;


|

tgl_lahir

pria

+++

BAB 7.

Bummi Dwi

Ce ep

Nita

(3

51

DATABASE

Putera

Zahrudin
Pandria

1985 08 17

1972 06 01

1976 09 19

rows )
Jika Anda kurang suka dengan eld pria yang bertipe boolean bisa dihapus

dengan perintah ALTER TABLE.


1
2

t o t a l i n d o=> ALTER TABLE p e g a w a i DROP p r i a ;


ALTER TABLE
Anda masih kurang berkenan dengan struktur tabel pegawai ?

Silahkan

hapus dengan perintah DROP TABLE.


1
2

t o t a l i n d o=> DROP TABLE p e g a w a i ;


DROP TABLE
SELECT, INSERT, UPDATE, dan DELETE adalah hal yang terkait dengan 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

Dibutuhkan sebuah laporan yang menampilkan data pegawai beserta usianya.


Untuk mendapatkan usia kita bisa gunakan rumus:

usia = tgl sekarang - tgl lahir


Lalu kita tampilkan dengan urutan diawali yang paling tua.
1

t o t a l i n d o=> SELECT i d ,

nama ,

now ( )

t g l _ l a h i r FROM

p e g a w a i ORDER BY t g l _ l a h i r ;
2
3

id

nama

? olumn ?

++

Arief

Setiadi

13957

days

11:21:54.083022

Ce ep

Zahrudin

13927

days

11:21:54.083022

Nita

Bummi Dwi

(4

Pandria
Putera

12356

9102

days
days

11:21:54.083022
11:21:54.083022

rows )
Kolom ketiga berisi usia, tapi PostgreSQL tidak tahu harus dinamakan apa,

sehingga jadilah bernama ? olumn?. Ada baiknya kita berikan nama usia.
1

t o t a l i n d o=> SELECT i d ,

t o t a l i n d o > FROM p e g a w a i ORDER BY t g l _ l a h i r ;

3
4

id

nama

nama ,

now ( )

tgl_lahir

AS

usia

usia

++

Arief

Setiadi

13957

days

11:28:34.001142

Ce ep

Zahrudin

13927

days

11:28:34.001142

BAB 7.

Nita

Bummi Dwi

(4

52

DATABASE

Pandria
Putera

12356

9102

days
days

11:28:34.001142
11:28:34.001142

rows )
Satuan usia menggunakan hari tentu saja kurang nyaman diba a. Sebaiknya

kita ganti rumusnya:

usia = tahun sekarang - tahun kelahiran


sehingga query-nya menjadi:
1

t o t a l i n d o=> SELECT i d ,

t o t a l i n d o > e x t r a t ( y e a r
tgl_lahir )

3
4
5

AS

nama ,
from

e x t r a t ( year

from

t o t a l i n d o > FROM p e g a w a i ORDER BY t g l _ l a h i r ;


id

nama

usia

++

Arief

Setiadi

38

Ce ep

Zahrudin

38

Nita

Bummi Dwi

10

now ( ) )

usia

(4

Pandria
Putera

34

25

rows )
Perintah SQL (query) di atas dapat disimpan dalam sebuah VIEW.

t o t a l i n d o=> CREATE VIEW v_pegawai AS SELECT i d ,

e x t r a t ( year
AS

from

now ( ) )

e x t r a t ( year

from

nama ,

tgl_lahir )

usia

FROM p e g a w a i ORDER BY t g l _ l a h i r ;

CREATE VIEW
Selanjutnya kita tampilkan VIEW tadi layaknya sebuah tabel.

1
2
3

t o t a l i n d o=> SELECT
id

FROM v_pegawai ;

nama

usia

++

Arief

Setiadi

38

Ce ep

Zahrudin

38

Nita

Bummi Dwi

(4

Pandria
Putera

34

25

rows )
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 menggunakan ORDER BY saat SELECT, misalnya diurut berdasar nama.
1
2

t o t a l i n d o=> SELECT
id

nama

FROM v_pegawai ORDER BY nama ;


|

usia

BAB 7.

++

Arief

Bummi Dwi

Ce ep

Nita

53

DATABASE

(4

Setiadi
Putera

Zahrudin
Pandria

38

25

38

34

rows )

7.3

Ba kup dan Restore

Jika tabel pegawai benar-benar Anda hapus, sebaiknya mulailah membuatnya


lagi dan mengisinya. Selain langsung melalui psql modus interaktif, Anda bisa
membuatnya dulu dalam sebuah le pegawai.sql.
Listing 7.1: pegawai.sql

1
2
3
4
5
6
7
8
9

CREATE TABLE
var har NOT NULL
date NOT NULL
NOT NULL DEFAULT true
PRIMARY KEY
pegawai (

id

serial ,

nama
pria

boolean

) ;

INSERT INTO
INSERT INTO
INSERT INTO
INSERT INTO

p e g a w a i ( nama , t g l _ l a h i r , p r i a )

P u t e r a ' , ' 1985 8 17 ' ,

true

true
true
false
);

p e g a w a i ( nama , t g l _ l a h i r , p r i a )

Z a h r u d i n ' , ' 1972 6 1 ' ,

12

);

p e g a w a i ( nama , t g l _ l a h i r , p r i a )

S e t i a d i ' , ' 1972 5 2 ' ,

11

( id )

Dwi

10

(30)

tgl_lahir

);

p e g a w a i ( nama , t g l _ l a h i r , p r i a )

P a n d r i a ' , ' 1976 9 19 ' ,

) ;

VALUES
VALUES
VALUES
VALUES

( ' Bummi
( ' Arief
( ' Ce ep
( ' Nita

Lalu di psql jalankan le tersebut:


1

t o t a l i n d o=> \ i

p s q l : s q l / pegawai . s q l : 7 :
impli it

pegawai . s q l

sequen e

NOTICE :

CREATE TABLE

" pegawai_id_seq "

for

will

serial

reate
olumn

" pegawai . i d "


3

p s q l : s q l / pegawai . s q l : 7 :
KEY w i l l
table

reate

NOTICE :

impli it

" pegawai "

CREATE TABLE

INSERT 0

INSERT 0

INSERT 0

INSERT 0

Kalau Anda menemui kegagalan

CREATE TABLE / PRIMARY

index

" p e g a w a i _ p ke y"

for

BAB 7.

54

DATABASE

No su h file or dire tory


obalah menuliskan nama le se ara fullpath, misalnya.
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

Sesuaikan dengan direktori dimana Anda menyimpan pegawai.sql. Mudahmudahan Anda mengerti maksudnya.
Kini ba kup database totalindo dalam sebuah le berformat tar.
1

$ pg_dump

ilham

totalindo

lo alhost

totalindo . sql . tar


Mulailah untuk latihan restore, yaitu dengan membuat database lain bernama totalindo_1 (lihat pembuatan database di awal bab ini).

pg_restore

ilham

lo alhost

Lalu jalankan:

totalindo_1

totalindo . sql . tar


Anda juga bisa ba kup menggunakan format teks biasa (plaintext):
1

$ pg_dump

ilham

totalindo

lo alhost

totalindo .

sql
dan restore dengan psql:
1

psql

ilham

totalindo_1

lo alhost

totalindo . sql

Manfaat penggunaan plaintext adalah Anda bisa mengubah le totalindo.sql menggunakan teks editor biasa. Namun penggunaan format ini terkadang
menimbulkan masalah saat restore bila ada karakter aneh, yaitu karakter dengan nomor ASCII lebih besar dari 126.

7.3.1 En oding
PostgreSQL versi terdahulu biasanya menggunakan SQL_ASCII sebagai en oding hara ter. Anda bisa lihat dengan perintah \l di psql.
1

psql

psql

(8.4.4)

ilham

Type

" help "

for

template1

lo alhost

help .

4
5

p o s t g r e s=# \ l

List

7
8
9
10
11
12
13
14

of

databases

Name

Owner

En oding

Collation

++++
postgres
| p o s t g r e s | UTF8
| id_ID . UTF8 |
template0
| p o s t g r e s | UTF8
| id_ID . UTF8 |
template1
| p o s t g r e s | UTF8
| id_ID . UTF8 |
totalindo
| ilham
| UTF8
| id_ID . UTF8 |
totalindo_1 | ilham
| UTF8
| id_ID . UTF8 |
(5

rows )

BAB 7.

55

DATABASE

Perhatikan di versi ini default en oding adalah UTF8. Jika Anda memba kup, 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

# su

sudo

su

postgres

reatedb

ilham

template0

sql_as ii

totalindo_2

Kembali ke psql dan lihat daftar database. Karena masih sebagai user postgres maka ukup ketik psql.
1

psql

psql
(8.4.4)

Type

" help "

for

help .

4
5

p o s t g r e s=# \ l

List

7
8
9
10
11
12
13
14
15

of

databases

Name

Owner

En oding

Collation

++++
postgres
| p o s t g r e s | UTF8
| id_ID . UTF8 |
template0
| p o s t g r e s | UTF8
| id_ID . UTF8 |
template1
| p o s t g r e s | UTF8
| id_ID . UTF8 |
totalindo
| ilham
| UTF8
| id_ID . UTF8 |
totalindo_1 | ilham
| UTF8
| id_ID . UTF8 |
totalindo_2 | ilham
| SQL_ASCII | id_ID . UTF8 |
(6

rows )
Mengenai ara ba kup dan restore lainnya sama seperti sebelumnya.
Mengapa kita perlu memperhatikan en oding ?
Bila database yang Anda ba kup tidak mengandung karakter aneh (ASCII

> 126) maka bisa dengan nyaman di-restore dari ke UTF8. Namun bila mengandung ASCII > 126 maka restore ke UTF8 dari sumber SQL_ASCII bisa
menimbulkan masalah.

7.4

Fungsi

Sama seperti Python, PostgreSQL juga mengenal fungsi. Contoh fungsi bawaan
(built-in) adalah now().
1

t o t a l i n d o=> SELECT now ( ) ;

2
3
4
5

now

2010 08 24 1 6 : 0 6 : 5 8 . 6 7 8 0 5 6 + 0 7
(1

row )
Keunikan fungsi pada PostgreSQL adalah pada nama dan susunan masukan-

nya (input parameter). Perhatikan ontoh rata kanan berikut ini.

BAB 7.

t o t a l i n d o=> SELECT l p a d ( ' A' , 5 ) ;

2
3

lpad

4
5

56

DATABASE

A
(1

row )
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().
1

t o t a l i n d o=> SELECT

length

4
5

l e n g t h ( l p a d ( ' A' , 5 ) ) ;

5
(1

row )
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

t o t a l i n d o=> SELECT l p a d ( ' 1 ' , 5 , ' 0 ' ) ;

2
3

lpad

4
5

00001
(1

row )
Di sinilah letak keunikan sebuah fungsi pada PostgreSQL. Fungsi lpad()

bisa menerima masukan dua buah atau tiga buah.

Jika dua buah saja yang

digunakan maka lpad() akan mengawalinya dengan spasi. Namun jika tiga buah
masukan, maka lpad() akan mengawalinya sesuai dengan karakter pada masukan
ketiga. Cermatilah baik-baik.
Jadi bila kita ingin membuat beberapa fungsi dengan nama sama maka harus
dibedakan dengan:
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.
1

sudo

su

postgres

" reatelang

plpgsql

totalindo "

BAB 7.

57

DATABASE

Selanjutnya siapkanlah dua konsole, yang pertama untuk


1

psql

ilham

totalindo

lo alhost

sedangkan yang kedua untuk text editor vi. Tentu saja Anda bisa menggunakan 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.

1
2
3
4
5
6
7
8

Listing 7.2: hello.sql

CREATE OR
RETURNS

REPLACE FUNCTION h e l l o ( )

text

LANGUAGE p l p g s q l

AS

$$

BEGIN
RETURN

END

' Hello

world . ' ;

$$ ;

Setelah disimpan jalankan di psql tadi:


1
2

t o t a l i n d o=> \ i

hello . sql

CREATE FUNCTION
lalu obalah

t o t a l i n d o=> SELECT

2
3
4
5

hello () ;

hello

Hello
(1

world .

row )

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.

ALTER TABLE

pegawai

ADD

saldo

float NOT NULL DEFAULT

0;

Kemudian untuk men atat aktivitas transaksi kita memerlukan tabel transaksi berikut ini.
Listing 7.3: transaksi.sql

1
2
3
4

CREATE TABLE
PRIMARY KEY
integer NOT NULL
timestamp NOT NULL DEFAULT
transaksi (

id

pid
tgl

serial

REFERENCES p e g a w a i ,
now ( ) ,

BAB 7.

var har
NOT NULL
float NOT NULL
float NOT NULL

ket

nominal

7
8

58

DATABASE

(100)

saldo
) ;

Misalkan ID pegawai 1 bernama Bummi Dwi Putera mendapat gaji untuk


bulan Nopember 2010 sebesar Rp 3.000.000,- maka query-nya adalah:
1

UPDATE p e g a w a i SET

s a l d o = s a l d o + 3 0 0 0 0 0 0 WHERE i d = 1 ;

2
3

INSERT INTO

t r a n s a k s i ( pid , ket , nominal , s a l d o )

SELECT i d , ' GAJI

FROM p e g a w a i

WHERE i d = 1 ;

11 2010 ' ,3000000 , s a l d o

Ya, kita butuh dua query untuk sebuah transaksi. Mungkin ada pertanyaan,
untuk apa eld saldo pada tabel transaksi ? Field ini digunakan untuk memudahkan 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 ? Keluaran atau output yang paling tepat adalah ID transaksi. Query-nya bisa kita
peroleh dengan ara berikut ini.
1

SELECT

i d FROM t r a n s a k s i ORDER BY i d DESC LIMIT

1;

Artinya dapatkan re ord terakhir dari tabel transaksi.


1
2
3

id

pid

tgl

+++
1 |
1 | 2010 10 22 1 7 : 5 8 : 0 1 . 8 6 |

4
5
6
7

ket

nominal

saldo

++
GAJI 11 2010 | 3 0 0 0 0 0 0 | 3 0 0 0 0 0 0
Selanjutnya kita buat fun transaksi.sql untuk fungsi dimaksud.

1
2
3
4
5

CREATE OR
integer
float
integer

Listing 7.4: fun transaksi.sql

REPLACE FUNCTION t r a n s a k s i (

p_pid
p_ket

text ,

p_nominal

RETURNS

BAB 7.

6
7
8

LANGUAGE p l p g s q l

AS

$$

DECLARE

re

10

BEGIN

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

59

DATABASE

re ord ;

UPDATE
SET
WHERE
INSERT INTO
SELECT
FROM
WHERE
SELECT
INTO
FROM
ORDER BY DESC
LIMIT
pegawai

s a l d o = s a l d o + p_nominal
i d = p_pid ;
transaksi (

id ,

pid ,

nominal ,

tid ,

ket ,

p_pid ,

saldo )

p_nominal ,

p_ket ,

saldo

pegawai

i d = p_pid ;

id

re

transaksi
id

1;

RETURN r e . i d ;

END
$$

Restore s ript ini.


1
2

t o t a l i n d o=> \ i

fun transaksi . sql

CREATE FUNCTION
Misalkan ID pegawai 1 meminjam ( ash bon) sebesar Rp200.000,- maka:

t o t a l i n d o=> SELECT

transaksi

4
5

t r a n s a k s i ( 1 , 'BON' ,

200000) ;

2
(1

row )
Perhatikan nominal berisi nilai negatif yang artinya mengurangi saldo. Sekarang

lihat keseluruhan transaksi.


1
2

t o t a l i n d o=> SELECT
id

pid

FROM t r a n s a k s i ;
tgl

nominal
3

|
|

ket

saldo

+++++
1

2010 10 22

3000000

3000000

17:58:01.869139

GAJI 11 2010

BAB 7.

2010 10 22

200000
6

(2

60

DATABASE

18:20:08.845091

| BON

2800000

rows )
Dilihat dari aspek ke epatan, query SELECT terhadap tabel transaksi bisa

dihindari. Maklumlah tabel transaksi ini tergolong epat pertumbuhan re ordnya. Jadi untuk mendapatkan ID transaksi kita perlu menggunakan sequen e
yang dimiliki tabel transaksi tersebut. Ubahlah fun transaksi.sql menjadi berikut
ini.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

CREATE OR
integer
float
integer
AS
integer
UPDATE
SET
WHERE

REPLACE FUNCTION t r a n s a k s i (

p_pid
p_ket

17
18
19
20
21
22
23
24
25

text ,

p_nominal

RETURNS

LANGUAGE p l p g s q l
$$

DECLARE
tid

BEGIN

pegawai

s a l d o = s a l d o + p_nominal
i d = p_pid ;

15
16

Listing 7.5: fun transaksi.sql

t i d = nextval ( ' transaksi_id_seq ' ) ;

INSERT INTO
SELECT
FROM
WHERE
id ,

pid ,

transaksi (

nominal ,

tid ,

ket ,

p_pid ,

saldo )

p_nominal ,

p_ket ,

saldo

pegawai
i d = p_pid ;

RETURN t i d ;

END
$$

Restore.
1
2

t o t a l i n d o=> \ i

transaksi . sql

CREATE FUNCTION
Kini kita oba ID pegawai 5 bernama Ilham untuk transaksi.

t o t a l i n d o=> SELECT

transaksi

4
5

3
(1

row )

t r a n s a k s i ( 5 , ' GAJI

11 2010 ' ,1500000) ;

BAB 7.

61

DATABASE

Lalu lihat hasilnya.


1

id

pid

tgl
|

ket

saldo

+++++

2010 10 22

3000000
5

|
|

17:58:01.869139

GAJI 11 2010

18:20:08.845091

| BON

18:41:45.309451

3000000
2800000

2010 10 22

1500000
(3

2010 10 22

200000

FROM t r a n s a k s i ;

nominal
3

t o t a l i n d o=> SELECT

GAJI 11 2010

1500000

rows )

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.
1

sudo

a p t g e t

sudo

su

install

Kali ini akan kita gunakan pada fungsi di PostgreSQL. Buatlah uang.sql

postgres

p o s t g r e s q l p l p y t h o n
" reatelang

8.4

plpythonu

totalindo "

Masih ingat modul uang yang ditaruh di /usr/lo al/lib/python2.6/dist-pa kages


berikut ini.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

CREATE OR
RETURNS

Listing 7.6: uang.sql


REPLACE FUNCTION uang ( n

text

float

LANGUAGE p l p y t h o n u

AS
from

$$
uang

return

import

uang

uang ( n )

$$ ;

CREATE OR
RETURNS

REPLACE FUNCTION uang ( n

text

integer

LANGUAGE p l p y t h o n u

AS
from

$$
uang

return

import

uang

uang ( n )

$$ ;
Tidak seperti plpgsql, fungsi yang ditulis menggunakan plpythonu harus
dibuat oleh user postgres.

BAB 7.

[ sudo

62

DATABASE

sudo

su

postgres

password

CREATE FUNCTION

CREATE FUNCTION

for

"psql

totalindo

sugiana :

Lalu obalah.
1

t o t a l i n d o=> SELECT uang ( 1 0 0 0 0 ) ;

uang

4
5

10.000
(1

row )

uang . s q l "

Bab 8

Python Akses Database


Data yang ada di PostgreSQL dapat digunakan oleh aplikasi yang ditulis dengan bahasa Python menggunakan pustaka tambahan bernama SQLAl hemy.
Pustaka ini dipilih karena sifatnya yang luwes dimana ia juga bisa menangani
database lainnya, tidak hanya PostgreSQL.
Sekarang pasanglah terlebih dahulu.
1

sudo

a p t g e t

install

python s q l a l h e m y

sudo

a p t g e t

install

python p s y o p g 2

Selanjutnya masuk ke modus interaktif untuk men oba.


1

>>> i m p o r t

>>> u r l =

sqlal hemy

as

sa

>>> db = s a . r e a t e _ e n g i n e ( u r l )

>>> db . o n n e t ( )

<s q l a l h e m y . e n g i n e . b a s e . C o n n e t i o n

' p o s t g r e s q l : / / ilham :1234 lo alhost / t o t a l i n d o '

obje t

at

0 x8b0872 >

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.
>>> s q l

>>> q = db . e x e u t e ( s q l )

>>> f o r

...

= "SELECT

in

print

FROM p e g a w a i "

q:
r

...

(1 ,

' Bummi Dwi

(2 ,

' Arief

(3 ,

' Ce ep

(4 ,

' Nita

Putera ' ,

Setiadi ' ,
Zahrudin ' ,
Pandria ' ,

datetime . date (1985 ,

datetime . date (1972 ,


datetime . date (1972 ,

datetime . date (1976 ,

8,

5,
9,

17) ,

2) ,

6,

1) ,

19) ,

True )

True )
True )
False )

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.

64

PYTHON AKSES DATABASE

>>> q = db . e x e u t e ( s q l )

>>> f o r

in

...

print

...

1 Bummi Dwi

Arief

Ce ep

Nita

q:
r [ ' id ' ,

r [ ' nama '

Putera

Setiadi
Zahrudin
Pandria

Bahkan eld id dan nama bisa dianggap variabel milik r:


1

>>> q = db . e x e u t e ( s q l )

>>> f o r

in

...

print

...

1 Bummi Dwi

Arief

Ce ep

Nita

q:
r . id ,

r . nama

Putera

Setiadi
Zahrudin
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.
1

>>> s q l

>>> db . e x e u t e ( s q l )

= "UPDATE p e g a w a i SET nama = u p p e r ( nama ) "

<s q l a l h e m y . e n g i n e . b a s e . R e s u l t P r o x y

>>> s q l

>>> q = db . e x e u t e ( s q l )

>>> f o r

7
8
9

...

= "SELECT
r

in

print

obje t

at

0 x b 7 4 8 a 9 a >

FROM p e g a w a i "

q:
r . nama

...
BUMMI DWI PUTERA

10

ARIEF SETIADI

11

CECEP ZAHRUDIN

12

NITA PANDRIA

8.1

A tive Re ord

Anda memiliki data pegawai dalam sebuah le yang berformat CSV yang isinya
seperti ini:
Listing 8.1: pegawai. sv
1

1 ;BUMMI DWI PUTERA,

ST; 1 9 8 5 0 8 1 7 ; t

2 ; ARIEF SETIADI ; 1 9 7 2 0 5 0 2 ; t

3 ;CECEP ZAHRUDIN; 1 9 7 2 0 6 0 1 ; t

BAB 8.

65

PYTHON AKSES DATABASE

4 ; NITA PANDRIA; 1 9 7 6 0 9 1 9 ; f

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.

Password

psql

psql

SSL

Type

ilham
for

user

lo alhost

totalindo

ilham :

(8.4.4)
onne tion
" help "

( ipher :

for

DHERSAAES256SHA,

bits :

256)

help .

6
7
8
9
10
11
12
13
14

t o t a l i n d o=> SELECT
id

FROM p e g a w a i ;

nama

tgl_lahir

pria

+++
1 | BUMMI DWI PUTERA | 1985 08 17 | t
2 | ARIEF SETIADI
| 1972 05 02 | t
3 | CECEP ZAHRUDIN
| 1972 06 01 | t
4 | NITA PANDRIA
| 1976 09 19 | f
(4

rows )
Bandingkanlah dengan le pegawai. sv sebelumnya dimana perubahannya

nanti adalah:
1. ID 1 nama akan berubah dari BUMMI DWI PUTERA menjadi BUMMI
DWI PUTERA, ST (bergelar).
2. Jumlah baris tabel pegawai bertambah dengan adanya ID 5 bernama ILHAM.
Buatlah le pegawai. sv terlebih dahulu dengan isi seperti di atas. Kemudian
buatlah le updatepegawai.py.

1
2

import

Listing 8.2: updatepegawai.py


sqlal hemy

as

sa

url =

db = s a . r e a t e _ e n g i n e ( u r l )

' p o s t g r e s q l : / / ilham :1234 lo alhost / t o t a l i n d o '

db . o n n e t ( )

6
7

filename =

f = open ( f i l e n a m e )

9
10

for

line
pid ,

in

' pegawai . sv '


f . readlines () :

nama ,

tgl_lahir ,

pria = line . strip () . s p l i t ( ' ; ' )

BAB 8.

11

pid = i n t ( pid )

12

p r i a = p r i a ==

13

sql

14

q = db . e x e u t e ( s q l )

if

15
16

66

PYTHON AKSES DATABASE

= "SELECT

't '

# Agar b o o l e a n True / F a l s e

FROM p e g a w a i WHERE i d = %d " % p i d

q . row ount :
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

else

22
23

s q l = s q l % ( nama ,

tgl_lahir ,

pria ,

s q l = "INSERT INTO p e g a w a i
" ( id ,

25

"SELECT %d ,

'% s ' ,

'% s ' , %s "

s q l = s q l % ( pid ,

nama ,

tgl_lahir ,

27

nama ,

" + \

24
26

pid )

:
tgl_lahir ,

pria )

" + \
pria )

db . e x e u t e ( s q l )
Jalankan.

python

u p d a t e p e g a w a i . py

Kemudian ke psql, lihat tabel pegawai.


1

t o t a l i n d o=> SELECT

2
3
4
5
6
7
8
9

id

FROM p e g a w a i ORDER BY i d ;

nama

tgl_lahir

pria

+++
1 | BUMMI DWI PUTERA, ST | 1985 08 17 | t
2 | ARIEF SETIADI
| 1972 05 02 | t
3 | CECEP ZAHRUDIN
| 1972 06 01 | t
4 | NITA PANDRIA
| 1976 09 19 | f
5 | ILHAM
| 1984 11 05 | t
(5

rows )
Perubahan sudah sesuai dengan yang diharapkan.

Meski begitu sour e

updatepegawai.py tergolong sulit diba a, dan ini bisa menyulitkan debugging


(penelusuran kesalahan). Cara yang lebih nyaman adalah menggunakan teknik
yang disebut

a tive re ord

Terlebih dahulu pasang paket Elixir.


1

sudo

a p t g e t

install

python e l i x i r

Agar proses UPDATE dan INSERT masih terasa, buatlah perubahan pada
pegawai. sv berikut ini.
Listing 8.3: pegawai. sv
1

1 ;BUMMI DWI PUTERA,

2 ; ARIEF SETIADI ; 1 9 7 2 0 5 0 2 ; t

ST; 1 9 8 5 0 8 1 7 ; t

3 ;CECEP ZAHRUDIN ,

ST; 1 9 7 2 0 6 0 1 ; t

BAB 8.

67

PYTHON AKSES DATABASE

4 ; NITA PANDRIA; 1 9 7 6 0 9 1 9 ; f

5 ; ILHAM; 1 9 8 4 1 1 0 5 ; t

6 ;MIRANDA; 1 9 7 8 1 0 0 1 ; f
Perubahannya adalah UPDATE pada CECEP ZAHRUDIN menjadi CECEP ZAHRUDIN, ST, dan INSERT pada MIRANDA. Selanjutnya buat le
updatepegawai1.py.

Listing 8.4: updatepegawai1.py

from

import

elixir

metadata ,

2
3
4
5

Entity ,

using_options ,

setup_all ,

session

lass

Pegawai ( E n t i t y ) :

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

filename =

11

f = open ( f i l e n a m e )

12
13

for

' pegawai . sv '

in

line
pid ,

f . readlines () :

nama ,

tgl_lahir ,

pria = line . strip () . s p l i t ( ' ; ' )

14

pid = i n t ( pid )

15

p = P e g a w a i . q u e r y . f i l t e r _ b y ( i d=p i d )

if
else

16

p . ount ( ) :

17
18
19
20

r = p . one ( )
:
r = Pegawai ( )
r . id = pid

21

r . nama = nama

22

r . tgl_lahir = tgl_lahir

23

r . p r i a = p r i a ==

24

s e s s i o n . ommit ( )

't '

Jalankanlah.
1

python

u p d a t e p e g a w a i 1 . py

Lalu lihat hasilnya di psql.


1
2
3
4
5
6

t o t a l i n d o=> SELECT
id

nama

FROM p e g a w a i ORDER BY i d ;
|

tgl_lahir

pria

+++
1 | BUMMI DWI PUTERA, ST | 1985 08 17 | t
2 | ARIEF SETIADI
| 1972 05 02 | t
3 | CECEP ZAHRUDIN , ST
| 1972 06 01 | t

BAB 8.

68

PYTHON AKSES DATABASE

NITA PANDRIA

1976 09 19

ILHAM

1984 11 05

| MIRANDA

1978 10 01

9
10

6
(6

rows )
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.

from

import

elixir

setup_all ,

2
3
4
5
6
7
8
9
10
11
12
13
14

import
lass

Listing 8.5: deletepegawai.py


Entity ,

using_options ,

metadata ,

session
sys
Pegawai ( E n t i t y ) :

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 )

if not

sys . argv [ 1 : :

s y s . e x i t ( ' Caranya :

try
ex ept

p y t h o n %s <i d > ' % s y s . a r g v [ 0 )

pid = i n t ( sys . argv [ 1 )


ValueError :

s y s . e x i t ( ' ID

pegawai

harus

angka ' )

15
16

metadata . b i n d =

' p o s t g r e s : / / ilham :1234 lo alhost /

totalindo '
17

setup_all ()

18
19
20
21

p = P e g a w a i . q u e r y . f i l t e r _ b y ( i d=p i d )

if not

p . ount ( ) :

s y s . e x i t ( ' ID

p e g a w a i %d

tidak

ada ' % p i d )

22
23

r = p . one ( )

24

r . delete ()

25

print

26

s e s s i o n . ommit ( )
' ID

p e g a w a i %d

sudah

dihapus ' % pid

S ript ini membutuhkan parameter masukan (argument) saat dijalankan,


yaitu berupa ID pegawai yang akan dihapus. Kita oba menghapus ID pegawai
4 NITA PANDRIA.
1

ID

python

d e l e t e _ p e g a w a i . py

pegawai

sudah

dihapus

Periksa hasilnya di psql.

BAB 8.

1
2
3
4
5
6
7
8
9

t o t a l i n d o=> SELECT
id

69

PYTHON AKSES DATABASE

FROM p e g a w a i ORDER BY i d ;

nama

tgl_lahir

pria

+++
1 | BUMMI DWI PUTERA, ST | 1985 08 17 | t
2 | ARIEF SETIADI
| 1972 05 02 | t
3 | CECEP ZAHRUDIN , ST
| 1972 06 01 | t
5 | ILHAM
| 1984 11 05 | t
6 | MIRANDA
| 1978 10 01 | f
(5

rows )
Bagaimana dengan SELECT ? Contoh sebelumnya menggunakan lter_by()

yang sama artinya dengan WHERE. Kini kita tampilkan semua re ord tabel pegawai tanpa kondisi apapun yaitu mengganti lter_by() dengan all(). Buatlah
sele tpegawai.py.

from
import
lass

elixir

import

Listing 8.6: sele tpegawai.py


Entity ,

using_options ,

metadata ,

setup_all

2
3
4
5

sys
Pegawai ( E n t i t y ) :

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 ()

for

10
11

in
print
r

Pegawai . q u e r y . a l l ( ) :
r . id ,

r . nama ,

r . tgl_lahir ,

r . pria

Jalankan.

$
1
2
3
5
6

python sele t_pegawai.py


BUMMI DWI PUTERA, ST 1985-08-17 True
ARIEF SETIADI 1972-05-02 True
CECEP ZAHRUDIN, ST 1972-06-01 True
ILHAM 1984-11-05 True
MIRANDA 1978-10-01 False

Butuh tampilan yang urut berdasarkan nama ? Kita biasa menggunakan ORDER BY pada query, disini bisa menggunakan order_by() sebagai pengganti
all().

from
import

Listing 8.7: sele tpegawai2.py

elixir

import

setup_all

sys

Entity ,

using_options ,

metadata ,

BAB 8.

3
4
5

70

PYTHON AKSES DATABASE

lass

Pegawai ( E n t i t y ) :

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 ()

for

10
11

in
print
r

P e g a w a i . q u e r y . o r d e r _ b y ( ' nama ' ) :


r . id ,

r . nama ,

r . tgl_lahir ,

r . pria

Jalankan.
1

2 ARIEF SETIADI 1972 05 02 True

python

s e l e t _ p e g a w a i . py

1 BUMMI DWI PUTERA,

3 CECEP ZAHRUDIN ,

5 ILHAM 1984 11 05 True

6 MIRANDA 1978 10 01

ST 1985 08 17 True

ST 1972 06 01 True
False

Ingin yang lebih rapi ? Ubahlah seperti ini.

1
2
3
4
5

from
import
lass

elixir
sys

import

Listing 8.8: sele tpegawai.py

Pegawai ( E n t i t y ) :

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

jenis

= { True :

11

False :

' Pria ' ,


' Wanita ' }

12
13
14
15

p = P e g a w a i . q u e r y . o r d e r _ b y ( ' nama ' )

for

16

in
print
r

p:
str ( r . id ) . enter (3) ,

r . nama . l j u s t ( 2 0 ) ,

17

r . tgl_lahir ,

18

jeni s [ r . pria

Jalankan.
1

python

s e l e t _ p e g a w a i . py

ARIEF SETIADI

BUMMI DWI PUTERA,

1972 05 02

Pria

ST 1985 08 17

Pria

BAB 8.

71

PYTHON AKSES DATABASE

CECEP ZAHRUDIN ,

1972 06 01

Pria

ILHAM

ST

1984 11 05

Pria

MIRANDA

1978 10 01 Wanita

Elixir vs SQLAl hemy ?


Sebenarnya Elixir bukanlah menggantikan SQLAl hemy, karena Elixir sendiri
menggunakan engine SQLAl hemy.

Ini bisa terlihat pada penjelasan paket

python-elixir.
1

Pa kage :

dpkg

python e l i x i r
python e l i x i r

Version :

0.7.1 1

Depends :

p y t h o n (>=

2.4) ,

python s q l a l h e m y
5

Des ription :

8.2

(>=

De larative

python s u p p o r t (>=

0.90.0) ,

0.4.0)
Mapper

for

SQLAl hemy

Auto Commit

Masih ingat fungsi sql bernama transaksi() ? Kali ini akan kita buat transaksi
perbankan se ara interaktif. Buatlah transaksi.py berikut.

1
2
3

import
import

Listing 8.9: transaksi.py


sqlal hemy

as

sa

sys

url =

db = s a . r e a t e _ e n g i n e ( u r l )

print
try
ex ept

7
8
9
10
11
12

' p o s t g r e s q l : / / ilham :1234 lo alhost / t o t a l i n d o '

' Transaksi '

p i d = r a w _ i n p u t ( ' ID

pegawai :

')

pid = i n t ( pid )
ValueError :

s y s . e x i t ( ' ID

p e g a w a i %s

tidak

benar ' % pid )

13
14

sql

15

q = db . e x e u t e ( s q l )

16
17
18
19
20
21
22

= "SELECT nama FROM p e g a w a i WHERE i d = %d " % p i d

if not
print

q . row ount :

s y s . e x i t ( ' ID
' Nama : ' ,

p e g a w a i %d

k e t = raw_input ( ' Keterangan :

if not

tidak

ada ' % p i d )

q . f e t h o n e ( ) . nama
')

ket :

s y s . e x i t ( ' Keterangan

harus

diisi ')

BAB 8.

72

PYTHON AKSES DATABASE

23
24
25
26
27
28

n o m i n a l = r a w _ i n p u t ( ' Nominal :

try
ex ept

')

nominal = f l o a t ( nominal )
ValueError :

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
32

q = db . e x e u t e ( s q l )

print

' Transaksi

berhasil ,

ID ' ,

q . fet hone () . transaksi

Jalankan.
1

Transaksi

python

t r a n s a k s i . py

ID

Nama :

pegawai :

Keterangan :

Nominal :

Transaksi

CECEP ZAHRUDIN ,

ST

GAJI 11 2010

4500000
berhasil ,

ID

Untuk memastikan transaksi benar-benar berhasil, lihatlah di psql.


1
2
3
4
5
6
7

t o t a l i n d o=> SELECT
id

pid

FROM t r a n s a k s i ;

tgl

ket

nominal

saldo

+++++
1 |
1 | 2010 10 22 | GAJI 11 2010 | 3 0 0 0 0 0 0 | 3 0 0 0 0 0 0
2 |
1 | 2010 10 22 | BON
| 200000 | 2 8 0 0 0 0 0
3 |
5 | 2010 10 22 | GAJI 11 2010 | 1 5 0 0 0 0 0 | 1 5 0 0 0 0 0
(3

rows )
Perhatikan, tidak ada ID transaksi 4, padahal eksekusi transaksi.py berjalan

baik. Apa yang terjadi ?


SQL fun tion transaksi() yang dijalankan oleh transaksi.py dijalankan pada
modus

transa tion

. Ini bisa diartikan SQLAl hemy atau mungkin Psy opg2

yang digunakan SQLAl hemy otomatis menjalankan BEGIN sebelum SELECT


transaksi( ... ). Seperti kita ketahui BEGIN tanpa COMMIT sama artinya dengan ROLLBACK. Itu artinya semua aktitas DML seperti INSERT, UPDATE,
DELETE setelah BEGIN dibatalkan, seolah tidak terjadi.
Solusinya adalah memberitahukan SQLAl hemy untuk menjalankan

ommit

. Ubahlah transaksi.py menjadi berikut ini.

1
2
3
4

import
from
import

Listing 8.10: transaksi.py


sqlal hemy

as

sa

sqlal hemy . s q l . expression


sys

import

text

auto

BAB 8.

url =

db = s a . r e a t e _ e n g i n e ( u r l )

print
try
ex ept

8
9
10
11
12
13

73

PYTHON AKSES DATABASE

' p o s t g r e s q l : / / ilham :1234 lo alhost / t o t a l i n d o '

' Transaksi '

p i d = r a w _ i n p u t ( ' ID

pegawai :

')

pid = i n t ( pid )
ValueError :

s y s . e x i t ( ' ID

p e g a w a i %s

tidak

benar ' % pid )

14
15

sql

16

q = db . e x e u t e ( s q l )

17
18
19
20
21
22
23

= "SELECT nama FROM p e g a w a i WHERE i d = %d " % p i d

if not
print

q . row ount :

s y s . e x i t ( ' ID
' Nama : ' ,

p e g a w a i %d

tidak

k e t = raw_input ( ' Keterangan :

if not

ada ' % p i d )

q . f e t h o n e ( ) . nama
')

ket :

s y s . e x i t ( ' Keterangan

harus

diisi ')

24
25
26
27
28
29

n o m i n a l = r a w _ i n p u t ( ' Nominal :

try
ex ept

')

nominal = f l o a t ( nominal )
ValueError :

s y s . e x i t ( ' Nominal %s

tidak

benar ' % nominal )

30
31

sql

= "SELECT

t r a n s a k s i (%d , ' % s ' , % . 2 f ) " % ( p i d ,

ket ,

nominal )
32
33

q = db . e x e u t e ( t e x t ( s q l ,

print

' Transaksi

a u t o o m m i t=True ) )

berhasil ,

ID ' ,

q . fet hone () . transaksi

Penambahan pada baris 2:

from sqlal hemy.sql.expression import text


dan perubahan pada baris 32 dari

q = db.exe ute(sql)
menjadi

q = db.exe ute(text(sql, auto ommit=True))


8.3

Syn hronizer

Pelanggan Anda memiliki usaha di bidang mini market dan telah memiliki beberapa outlet. Semua outlet itu telah terhubung ke Internet. Internet digunakan

BAB 8.

74

PYTHON AKSES DATABASE

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 (Internet Servi e Provider) bersangkutan. Setelah IP publik didapat, tambahkan
baris berikut ini di

/et /postgresql/8.4/main/pg_hba. onf:

host all all 0.0.0.0/0 md5


Kongurasi ini artinya semua host dapat mengakses database pusat, tentunya
dengan otentikasi username dan password. Simpan dan restart daemon-nya:
1

sudo

Restarting

servi e

postgresql

PostgreSQL

8.4

8.4

restart

database

server

Kini saatnya uji konektivitas database. Misalkan IP publiknya adalah 110.137.120.251,


maka jalankan
1

psql

di outlet

ilham

110.137.120.251

totalindo

Di s ript Python gantilah lo alhost dengan IP publik tadi.

url = 'postgresql://ilham:1234110.137.120.251/totalindo'
Mudah bukan ?

8.3.1 Aspek Keamanan


Tapi nanti dulu. Meski outlet itu hanya mendapat akses terbatas di database
pusat, namun tetap saja ini masih menimbulkan resiko keamanan data. Alangkah
baiknya menggunakan teknik sebaliknya, yaitu

syn hronizer berada di pusat

Dengan kata lain pusat-lah yang memba a database outlet, sedangkan outlet
tidak mendapat hak akses apapun di database pusat.
Lalu bagaimana host pusat mengakses host outlet ?

Apa perlu pesan IP

publik lagi ke ISP yang ada di outlet ?


Idealnya ya, namun tidak harus. Kita bisa menerapkan VPN alias Virtual
Private Network. Cukup pasang VPN server di pusat, dan pasang VPN lient

BAB 8.

75

PYTHON AKSES DATABASE

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
Apakah OpenVPN dapat bekerja di Windows mengingat masih banyak outlet
yang menggunakan sistem operasi ini ?
Ya, untungnya OpenVPN tersedia di untuk sistem operasi itu, dan tetap
dapat diatur agar otomatis aktif saat komputer dihidupkan.
Baik di pusat maupun di outlet jalankan perintah ini untuk mengetahi IP
VPN masing-masing:
1

tun0

if onfig

tun0
Link

e n a p : UNSPEC

HWaddr

00000000000000000000000000000000
3

inet

addr : 1 0 . 8 . 0 . 6

Pt P : 1 0 . 8 . 0 . 5

Mask

:255.255.255.255
4

UP POINTOPOINT RUNNING NOARP MULTICAST


:1500

MTU

Metri : 1

RX p a k e t s : 0

errors :0

dropped : 0

overruns :0

errors :0

dropped : 0

overruns :0

frame : 0
6

TX p a k e t s : 6
arrier :0

o l li s i on s :0

RX b y t e s : 0

txqueuelen :100

(0.0

B)

TX b y t e s : 9 6 3

( 9 6 3 . 0 B)

Tampak IP VPN di outlet adalah 10.8.0.6, sedangkan IP VPN di pusat


biasanya 10.8.0.1. Di host pusat, Anda juga bisa lihat IP masing-masing lient di
le

/et /openvpn/ipp.txt.

Jangan lupa untuk menguji konektivitas network

dengan perintah ping.


OpenVPN telah terpasang dan kedua host pusat dan outlet sudah bisa saling
ping. Selanjutnya apa yang harus dilakukan ?
Tambahkan baris berikut ini di

di outlet

/et /postgresql/8.4/main/pg_hba. onf

host all all 10.8.0.1/32 md5


Lalu restart daemon-nya.
1

sudo

Restarting

servi e

postgresql

PostgreSQL

8.4

8.4

restart

database

server

Di pusat lakukan uji konektivitas dengan psql.


1

psql

ilham

10.8.0.6

totalindo

Jika sudah terhubung baik, saatnya membuat s ript syn hronizer.

BAB 8.

76

PYTHON AKSES DATABASE

8.3.2 Tambah, Perbaharui, Hapus


Adalah sebuah tabel produk dengan struktur sebagai berikut:

1
2

reate table
id

produk (

primary key
not null unique
float not null

serial

nama name

harga

Listing 8.11: produk.sql

) ;

Isilah dengan beberapa re ord berikut ini:

INSERT INTO
INSERT INTO
INSERT INTO

SELECT
SELECT
SELECT

p r o d u k ( nama , h a r g a )

,10500;

p r o d u k ( nama , h a r g a )

,9250;

p r o d u k ( nama , h a r g a )

,14300;

' Jeruk

Pontianak '

' Salak

Pondoh '

' Mangga Indramayu '

Untuk menyamakan data produk, kita memerlukan dua perulangan (loop).


Yang pertama untuk INSERT dan UPDATE, sedangkan yang kedua untuk
DELETE. Berikut yang pertama:
1. Setiap

re ord pusat

diba a.

2. Field id menjadi a uan, karena dia primary key.


3. Jika id tidak ditemukan di outlet maka tambahkan.
4. Jika id ditemukan maka perbaharui.
Sedangkan untuk menghapus:
1. Setiap

re ord outlet

diba a.

2. Jika id tidak ditemukan di pusat maka hapus yang ada di outlet.


Lalu mulailah membuat syn .py berikut ini.

1
2

import
from
from
from

Listing 8.12: syn .py


sqlal hemy

elixir

metadata

3
4
5

import

as

s q l a l h e m y . orm

sa

Entity ,

using_options ,

import
import

s q l a l h e m y . s hema

s oped_session ,

setup_all ,
sessionmaker

ThreadLo alMetaData

6
7

es = sa . reate_engine ( ' p o s t g r e s q l : / / ilham :1234 lo alhost /


totalindo ' )

BAB 8.

77

PYTHON AKSES DATABASE

et = sa . reate_engine ( ' p o s t g r e s q l : / / ilham :1234 lo alhost /


totalindo2 ' )

9
10

s s = s o p e d _ s e s s i o n ( s e s s i o n m a k e r ( b i n d=e s ) )

11

s t = s o p e d _ s e s s i o n ( s e s s i o n m a k e r ( b i n d=e t ) )

12
13

ms = m e t a d a t a

14

mt = T h r e a d L o a l M e t a D a t a ( )

15
16

ms . b i n d = e s

17

mt . b i n d = e t

18
19
20
21

lass

ProdukS ( E n t i t y ) :

u s i n g _ o p t i o n s ( t a b l e n a m e= ' p r o d u k ' ,
m e t a d a t a=ms ,

22
23
24

lass

a u t o l o a d=True ,

s e s s i o n=s s )

ProdukT ( E n t i t y ) :

u s i n g _ o p t i o n s ( t a b l e n a m e= ' p r o d u k ' ,
m e t a d a t a=mt ,

a u t o l o a d=True ,

s e s s i o n=s t )

25
26
27
28

setup_all ()

# INSERT & UPDATE

29
30
31
32

all_ps =

for

33

in
print
try
print
ex ept
print
ps

ProdukS . q u e r y . a l l ( ) :
ps . id ,

p s . nama ,

34

p t = ProdukT . q u e r y . f i l t e r _ b y ( i d=p s . i d ) . o n e ( )

35
36

' diubah '

s a . orm . e x . NoResultFound ,

37
38

p t = ProdukT ( i d=p s . i d )

p t . nama = p s . nama

40

pt . harga = ps . harga

41

s t . ommit ( )

42

a l l _ p s . append ( p s . i d )

44
45
46
47
48
49
50

e:

' ditambah '

39

43

ps . harga ,

# DELETE

for

pt

if

in
not in
print

ProdukT . q u e r y . a l l ( ) :

pt . i d

pt . id ,

pt . d e l e t e ( )
s t . ommit ( )

all_ps :
p t . nama ,

pt . harga ,

' dihapus '

BAB 8.

8.4

78

PYTHON AKSES DATABASE

Migrasi dari Database Lain

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.
1

sudo

a p t g e t

install

python mysqldb

Lalu buatlah dbmigration.py berikut ini.

1
2
3
4
5
6

import
from
from
from
import

Listing 8.13: dbmigration.py


sqlal hemy

as

sa

import
import

s q l a l h e m y . s hema
s q l a l h e m y . orm
elixir
sys

import

ThreadLo alMetaData

s oped_session ,

7
8

dbs = s a . r e a t e _ e n g i n e ( s y s . a r g v [ 1 )

dbt = s a . r e a t e _ e n g i n e ( s y s . a r g v [ 2 )

sessionmaker

# sour e
# target

10

dbs . o n n e t ( )

11

dbt . o n n e t ( )

12

s e s s i o n _ s = s o p e d _ s e s s i o n ( s e s s i o n m a k e r ( b i n d=d b s ) )

13

s e s s i o n _ t = s o p e d _ s e s s i o n ( s e s s i o n m a k e r ( b i n d=d b t ) )

14

metadata_s = m e t a d a t a

15

metadata_t = T h r e a d L o a l M e t a D a t a ( )

16

metadata_s . b i n d = d b s

17

metadata_t . b i n d = d b t

18

for

19
20
21

tablename

lass

in

dbs . table_names ( ) :

Sour e ( Entity ) :

u s i n g _ o p t i o n s ( t a b l e n a m e=t a b l e n a m e , a u t o l o a d=True ,

22

m e t a d a t a=metadata_s , s e s s i o n=s e s s i o n _ s )

23
24

setup_all ()

25

lass

26
27
28
29
30

Target ( Entity ) :

u s i n g _ o p t i o n s ( t a b l e n a m e=t a b l e n a m e ,

for

m e t a d a t a=metadata_t , s e s s i o n=s e s s i o n _ t )
olumn

in

S o u r e . mapper . o l u m n s :

h a s _ f i e l d ( olumn . name ,

31

not

32

r e q u i r e d=

33

34
35
36

olumn . t y p e ,

p r i m a r y _ k e y= olumn . primary_key ,

s e t u p _ a l l ( True )

olumn . n u l l a b l e ,

BAB 8.

79

PYTHON AKSES DATABASE

Database

Paket

PostgreSQL

python-psy opg2

MySQL

python-mysqldb

SQLite

python-sqlite2

Interbase

python-kinterbasdb

MS SQL

python-pymssql

Tabel 8.1: Driver database

for

37
38

sour e

in

Sour e . query . a l l ( ) :

t a r g e t = Target ( )

39

t a r g e t . from_di t ( sour e . to_di t ( ) )

40

s e s s i o n _ t . ommit ( )
Contoh penggunaan:

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


Proses migrasi ini sudah menyertakan pembuatan tabel berikut onstraint
seperti PRIMARY KEY dan NULL.
Untuk driver database lainnya Anda bisa lihat di informasi paket pythonsqlal hemy, dan perhatikan bagian Suggests.
1

..

dpkg

Suggests :

python s q l a l h e m y
python s q l a l h e m y do ,

mysqldb (>= 1 . 2 . 1 p2 2) ,
pysqlite2
1.1.7 2)

(>= 2 . 3 . 0 1 )
|

kinterbasdb
4

python s q l i t e
(>=

3.1.2

..
Perhatikan bagian Suggests.

python p s y o p g 2 ,

p y t h o n (>=

2.5)

python p y s q l i t e 1 . 1
(>= 1 . 0 . 1 5 ) ,

0.3)

(>=

python

python p y m s s q l

python

python

Bab 9

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 ditulis dengan Python atau semua harus menggunakan PostgreSQL. Kali ini kita
oba pahami bagaimana komunikasi antar sistem bisa terjadi tanpa pemaksaan
platform tertentu.

9.1

Command Line

S ript Python Anda membutuhkan informasi mengenai network devi e berikut


IP-nya. Anda tidak tahu modul apa yang bisa digunakan. Namun Anda tahu
betul bahwa ommand line if ong sanggup melakukannya.
1

eth0

if onfig
Link

en ap : Ethernet

inet

addr : 1 9 2 . 1 6 8 . 1 1 . 1 1 1

HWaddr

0 0 : 2 5 : b3 : 7 7 : 3 e : 9 9

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

RX p a k e t s : 0

TX p a k e t s : 0

MTU: 1 5 0 0

Metri : 1

errors :0

dropped : 0

overruns :0

errors :0

dropped : 0

overruns :0

frame : 0
arrier :0
7

o l li s i on s :0

RX b y t e s : 0

txqueuelen :1000

(0.0

B)

TX b y t e s : 0

(0.0

B)

Interrupt :17

10
11

Link

en ap : Lo al

12

inet

addr : 1 2 7 . 0 . 0 . 1

13

inet6

14

lo

addr :

Loopba k
Mask : 2 5 5 . 0 . 0 . 0

::1/128

S ope : Host

UP LOOPBACK RUNNING

MTU: 1 6 4 3 6

80

Metri : 1

BAB 9.

81

LINTAS SISTEM

15

RX p a k e t s : 5 6 2

errors :0

dropped : 0

overruns :0

errors :0

dropped : 0

overruns :0

frame : 0
16

TX p a k e t s : 5 6 2
arrier :0

17

o l li s i on s :0

18

txqueuelen :0

RX b y t e s : 5 4 0 8 4 8

( 5 4 0 . 8 KB)

TX b y t e s : 5 4 0 8 4 8

( 5 4 0 . 8 KB)
19
20

Link

en ap : Ethernet

21

wlan0

inet

addr : 1 9 2 . 1 6 8 . 1 . 4

22

inet6

HWaddr

0 0 : 1 f : 3 : e0 : 6 6 : 5 6

B ast : 1 9 2 . 1 6 8 . 1 . 2 5 5

Mask : 2 5 5 . 2 5 5 . 2 5 5 . 0
addr :

fe80 : : 2 1 f : 3 f f : f e e 0 :6656/64

S ope :

Link
23

UP BROADCAST RUNNING MULTICAST

MTU: 1 5 0 0

Metri : 1
24

RX p a k e t s : 3 2 1 9

errors :0

dropped : 0

overruns :0

errors :0

dropped : 0

overruns :0

frame : 0
25

TX p a k e t s : 3 6 0 8
arrier :0

26

o l li s i on s :0

27

txqueuelen :1000

RX b y t e s : 1 5 8 6 2 9 7

( 1 . 5 MB)

TX b y t e s : 7 6 1 1 7 3

( 7 6 1 . 1 KB)
Bagaimana memanggil ommand line di s ript Python dan mengolah hasilnya ? Gunakan modul ommands. Buatlah netdev.py berikut ini.

1
2
3
4
5
6
7
8
9
10

import
import
def
for

Listing 9.1: netdev.py


ommands
re

netdev ( ) :
r = {}
line
() :
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

= line . strip ()

mat h = r e . o m p i l e ( ' ( . * ) L i n k

if

en ap ( . * ) ' ) . s e a r h (

line )
mat h :
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
14
15
16

if
ontinue

mat h :
r [ d e v i e [ ' addr '

mat h = r e . o m p i l e ( ' i n e t

= mat h . g r o u p ( 1 )
addr : ( . * ) ' ) . s e a r h ( l i n e )

BAB 9.

if
return

17
18
19
20
21
22
23

if

82

LINTAS SISTEM

mat h :
r [ devi e [ ' ip '

= mat h . g r o u p ( 1 ) . s p l i t ( ) [ 0

__name__ ==

'__main__ ' :

nd = n e t d e v ( )

for

24
25

in
print

dev

nd :
dev ,

nd [ d e v

Jalankan.
1

wlan0

python

lo

eth0

n e t d e v . py

{ ' ip ' :

{ ' ip ' :

'192.168.1.4 ' ,

' addr ' :

' 0 0 : 1 f : 3 : e0 : 6 6 : 5 6 ' }

'127.0.0.1 '}

{ ' 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 Anda 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, daemon 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.

9.3

83

LINTAS SISTEM

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 (bahasa Pas al) dan menggunakan database MySQL. Ia mengeluh pada Anda selaku developer outsour ing dimana komponen SMS gateway yang dibangunnya 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 ? Anda 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 menyediakan 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:

INSERT INTO

im . a n t r i a n ( p e n e r i m a ,

+628177654321 ' ,

' Selamat

pesan )

bergabung ' ;

SELECT

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.
1

SELECT

FROM im . a n t r i a n WHERE NOT k i r i m ;

Mudah bukan ? Lebih lanjut mengenai SMS gateway bisa lihat halaman115.

BAB 9.

84

LINTAS SISTEM

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 dibangun 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 dipilihlah 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 mengetahui username dan password untuk login ke database sistem utama.

Kalau

sudah begitu maka WP bisa melihat-lihat data nasabah lainnya, bahkan melihat 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 pertukaran 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
2

def

tambah ( a ,

return

b) :

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 menggunakan 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.

85

LINTAS SISTEM

Langkah apa yang harus dikembangkan terlebih dahulu ?


Jelas bahwa SAB harus mengembangkan XMLRPC server terlebih dahulu
yang berisi fungsi mutasi(). Mari kita mulai membuat le serverbank.py.

1
2
3
4
5
6

Listing 9.2: serverbank.py

from
import

SimpleXMLRPCServer

lass

sqlal hemy

as

sa

import

SimpleXMLRPCServer

S e r v e r ( SimpleXMLRPCServer ) :

a l l o w _ r e u s e _ a d d r e s s = True

def

8
9
10
11

verify_request ( self ,

request ,

lient_address ) :

server . ip_ lient = lient_address [ 0

print
return

server . ip_ lient

in

server . ip_ lient

[ ' 127.0.0.1 ' , '

192.168.0.1 ' , ' 192.168.1.5 '

12
13
14
15
16

def

r e s p ( ode ,

return

msg ) :

{ ' kode ' :

ode ,

' pesan ' :

msg }

17
18
19
20
21

lass
def

Agent :

22

_dispat h ( s e l f ,

print
try
ex ept
return
return

method ,

method ,

params =() ) :

params

23

fun = g e t a t t r ( s e l f ,

24

' e x p o r t _ ' + method )

AttributeError :

25

r e s p ( 1 ,

' F u n g s i %s

tidak

dikenal ' %

method )

f u n ( * params )

26
27
28
29

def

export_mutasi ( s e l f ,
s q l = "SELECT

p) :

t g l : : date ,

ket ,

nominal ,

saldo

" +

\
30

"FROM t r a n s a k s i WHERE p i d = %d " + \

31

"AND t g l : : d a t e BETWEEN '% s ' AND '% s '

32

"ORDER BY i d "

33

s q l = s q l % (p [ ' pid ' ,

34

q = db . e x e u t e ( s q l )

35

m =

36
37

for

[
r

in

p [ ' awal ' ,

" + \

p [ ' akhir ' )

q:

m. append ( [ s t r ( r . t g l ) ,
saldo )

r . ket ,

r . nominal ,

r.

BAB 9.

86

LINTAS SISTEM

38

r = r e s p ( 0 , 'OK ' )

39

return

r [ ' mutasi ' = m

40
41

42
43
44

url =

45

db = s a . r e a t e _ e n g i n e ( u r l )

' p o s t g r e s q l : / / ilham :1234 lo alhost / t o t a l i n d o '

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

print

51
52

s e r v e r . r e g i s t e r _ i n s t a n e ( Agent ( ) )
'HTTP XMLRPC s e r v e r

port ' ,

port

server . serve_forever ()
Jalankan.

HTTP XMLRPC s e r v e r

python

s e r v e r b a n k . py
port

9303

Proses seolah hang, tapi sebenarnya ia sedang menunggu permintaan (request) dari XMLRPC lient. Port 9303 hanya ontoh saja dimana Anda bisa
mengganti dengan nilai lainnya.

Se urity yang diterapkan di sini adalah IP

lient yang hanya menerima permintaan dari 127.0.0.1 dan 192.168.0.1.


Selanjutnya membuat XMLRPC lient bernama lientbank.py.

1
2

Listing 9.3: lientbank.py

import

xmlrp lib

url =

remote = x m l r p l i b . ServerProxy ( u r l )

' http : / / 1 2 7 . 0 . 0 . 1 : 9 3 0 3 '

d = { ' pid ' :

1,

' awal ' :

' akhir ' :

8
9
10

if

r [ ' k o d e ' == 0 :

for

12
14
15

' 20101023 ' }

r = remote . mutasi ( d )

11
13

' 20101022 ' ,

else

tgl ,

print

ket ,
tgl ,

nominal ,

saldo

ket . l j u s t (15) ,

in

r [ ' mutasi ' :

s t r ( i n t ( nominal ) ) . r j u s t ( 1 0 ) ,
s t r ( int ( saldo ) ) . r j u s t (10)

print

r [ ' pesan '

Bukalah konsole lainnya, lalu jalankan le ini.


1

2010 10 22 GAJI 11 2010

python

l i e n t b a n k . py
3000000

3000000

2010 10 22 BON

200000

2800000

BAB 9.

87

LINTAS SISTEM

Cermati baik-baik konsepnya. Juga perhatikan tipe data di tionary dan list
yang digunakan sebagai nilai keluaran (return value) dari fungsi mutasi.

9.4.1 PHP sebagai XMLRPC Client


Unduh xmlrp .in dari http://phpxmlrp .sour eforge.net.
xmlrp -2.2.2.tar.gz.

Carilah.

File itu berada di

Versi lain sepertinya juga tidak masalah.

Lalu

buatlah le lientbank.php.


Listing 9.4: lientbank.php
1
2
3
4
5

<?php

in lude
array

( ' xmlrp . i n ' )

$params = new

xmlrp val

' a w a l ' => new

7
9

xmlrp val

$ f = new xmlrp msg ( ' m u t a s i ' ,

12

$ = new

13

$ r = $ >s e n d ( $ f ) ;

14

$v = $ r >v a l u e ( ) ;

17

( ' 20101023 ' )

' stru t '


) ;

11

16

' int ' ) ,

( ' 20101022 ' ) ,

) ,

10

15

(1 ,

xmlrp val

' a k h i r ' => new

' p i d ' => new

xmlrp val

if

18

xmlrp _ lient( ' / '

( $ r >f a u l t C o d e ( ) )

print
else

if
forea h

array

( $params ) ) ;

' 127.0.0.1 ' ,

9303) ;

$r >f a u l t S t r i n g ( ) ;

$ r e s p = $ r >s a l a r v a l ( ) ;

19

( $ r e s p [ ' k o d e ' > s a l a r v a l ( ) == 0 )

20

( $ r e s p [ ' m u t a s i ' > s a l a r v a l ( )

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
str_pad
str_pad
str_pad
else
print

$tgl . "

27
28
29
30

".

( $ket ,

20) . "

( $nominal ,
( $saldo ,

".

10) . "

".

1 0 ) . " \n" ;

31

32

$ r e s p [ ' p e s a n ' > s a l a r v a l ( ) ;

33

34

35

?>

as

$ i=>$m)

BAB 9.

88

LINTAS SISTEM

Karena s ript ini akan kita jalankan sebagai ommand line, maka pasang
dulu paket terkait.
1

sudo

a p t g e t

install

php5 l i

Lalu jalankan.
1

2010 10 22 GAJI 11 2010

php

l i e n t _ b a n k . php
3000000

3000000

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.
Listing 9.5: pegawai.module
1

<?php

fun tion

pegawai_menu ( )

array

$items =

() ;

$ i t e m s [ ' p e g a w a i / t r x /%/%/% ' =

' t i t l e ' =>

' page

a l l b a k ' =>

' page

a r g u m e n t s ' =>

' a ess

array

' pegawai_trx ' ,

array

a l l b a k ' =>

(2 ,

3,

4) ,

' user_a ess ' ,

' t y p e ' => MENU_CALLBACK,

10

) ;

11
12

' Transaksi ' ,

return

$items ;

13
14

fun tion

15

$url =

16

$p =

17

pegawai_trx ( $pid ,

array

( ' p i d ' =>

20
21

if

( ! $r [ ' mutasi ' )

23

$ =

25
26

intval

( $pid ) ,

' a k h i r ' => $ a k h i r ) ;


$r = xmlrp ( $url ,

22
24

$akhir )

' a w a l ' => $ a w a l ,

18
19

$awal ,

' http : / / 1 2 7 . 0 . 0 . 1 : 9 3 0 3 ' ;

return

' mutasi ' ,

$p ) ;

drupal_set_message ( ' Tidak

ada

data ' ) ;

'<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> ' .


'<th>Nominal</th><th>S a l d o </th ></t r > ' ;

forea h

( $r [ ' mutasi '

$tgl = $f [ 0 ;

1 http://drupal.org

as

$ i=>$ f )

BAB 9.

89

LINTAS SISTEM

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

35

.=

' </ t r > ' ;

36

return

37

38

?>

$ ;

Juga buat sites/all/modules/pegawai/pegawai.info.


Listing 9.6: pegawai.info
1

name = P e g a w a i

d e s r i p t i o n = Data

ore = 6. x

v e r s i o n = " 6 . x 1.0"

pegawai

Setelah login di browser, masuklah ke menu admin/build/modules. Centang


modul pegawai dan klik Save. Lalu masukkan URL di browser seperti

pegawai/trx/1/20101022/20101023

Bab 10

Pengemasan
10.1

Paket Debian

Pada bab sebelumnya kita sudah membuat modul uang.py. Agar modul ini dapat digunakan oleh user lainnya maka diletakkanlah di direktori /usr/lo al/lib/python2.6/distpa kages. Proses opy modul seperti ini memang sudah mudah, tapi ada lagi
yang lebih memudahkan, yaitu dengan mengemasnya dalam bentuk paket Debian.
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 ./
2. Perbaharui daftar paket
$ sudo apt-get update
3. Pasang paket dimaksud
$ sudo apt-get install python-uang
Manfaat lain pemaketan adalah mudahnya pemasangan paket lainnya yang
dibutuhkan oleh paket utama, sering disebut sebagai

dependen ies

. Misalkan

paket python-uang tadi membutuhkan python-sqlal hemy, maka pada saat


1

sudo

a p t g e t

install

python uang

otomatis python-sqlal hemy juga ikut dipasang.


Penamaan python-uang dimana ada awalan python- dikarenakan
uang.py adalah modul Python yang umum. Dengan kata lain bisa
digunakan di aplikasi apa saja.

Tidak ada koneksi database di

sana. Juga tidak ada perintah akses database seperti SELECT dkk.
Awalan ini juga meniru dari paket umum lainnya seperti pythonsqlal hemy, python-psy opg2, python-serial, dst.

90

BAB 10.

91

PENGEMASAN

Mulailah membuat direktori kerja, yaitu /usr/lo al/sr /python-uang.


1

sudo

mkdir

/ u s r / l o a l / s r / python uang /DEBIAN

Perintah ini otomatis membuat dua buah direktori yaitu


1. /usr/lo al/sr /python-uang
2. /usr/lo al/sr /python-uang/DEBIAN
Direktori DEBIAN digunakan untuk meletakkan le-le yang berkaitan dengan
sistem paket seperti

ontrol
postinst

berisi informasi seputar paket.


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().


id_ID.UTF-8.

Jadi tidak hard- ode menggunakan lo ale

Dengan begitu python-uang semakin umum (general).

Dengan didaftarkannya /et /uang. onf di dalam onles, maka terhindar dari penibanan (timpa / overwrite) saat upgrade berlangsung. Misalkan kini python-uang versi 0.1. Kemudian dibuatlah versi 0.2 yang juga
memuat /et /uang. onf.

Jika

di dalam
sudah terpasang

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

. Karena siapa tahu

Anda sudah mengganti isi /et /uang. onf terpasang dengan de_DE.ISO8859-1. Dengan begitu kita terhindar dari mengubah ulang kongurasi.
Mudah-mudahan paham maksudnya.
Mulailah membuat le python-uang/DEBIAN/ ontrol.
Listing 10.1: DEBIAN/ ontrol
1

Pa kage :

Priority :

python uang

Se tion :

Maintainer :

Ar hite ture :

Version :

0.1

Depends :

python e n t r a l

Python V e r s i o n :

Des ription :

optional
python
Owo S u g i a n a <s u g i a n a  r a b . o . i d >
all
(>=

0.6.7)

all

Format

uang

Lanjutkan dengan membuat direktori modulnya.

BAB 10.

sudo

92

PENGEMASAN

/ usr/ l o a l / sr
mkdir

uang / s i t e

p python uang / u s r / s h a r e / p y e n t r a l / python


p a k a g e s

Perhatikanlah direktori setelah /usr/lo al/sr /python-uang. Semua direktori tersebut nantinya akan dipasang di root dire tory ( / ), ke uali direktori
DEBIAN.
Lalu mengapa menggunakan /usr/share ? Padahal sebelumnya kita meletakkan uang.py di /usr/lo al ? Direktori /usr/lo al yang kita gunakan sebelumnya bermakna bahwa uang.py belum menjadi bagian dari paket Debian. Bila
sudah menjadi bagian dari paket Debian, maka diletakkan di /usr/share. Begitulah ketentuan umumnya.
1

sudo

/ 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.
Listing 10.2: usr/share/py entral/python-uang/site-pa kages/uang.py

1
2
3

import
from

lo ale

ConfigParser

import

ConfigParser

onf = ConfigParser ()

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
13
14

def
if

17
19

23
24
25

p e a h a n=None ) :
None :

t y p e ( n i l a i ) == t y p e ( 0 ) :
:

p e a h a n = DECIMAL

18

22

is

pe ahan = 0

16

21

pe ahan

if
else
return

15

20

uang ( n i l a i ,

if

l o a l e . f o r m a t ( '%%.%d f ' % p e a h a n ,

__name__ ==

'__main__ ' :

n = 10000.5

print
print
print

uang ( n )
uang ( i n t ( n ) )
uang ( n , 3 )

nilai ,

True )

BAB 10.

93

PENGEMASAN

Buat direktori et .
1

sudo

mkdir

python uang / e t

Selanjutnya buat python-uang/et /uang. onf.


Listing 10.3: et /uang. onf
1

[ default

l o a l e = id_ID . UTF8

de imal = 2
Lalu buat python-uang/DEBIAN/ onles berisi satu baris berikut.
Listing 10.4: DEBIAN/ onles

/ e t / uang . o n f
Kemudian buat python-uang/DEBIAN/postinst yang berisi perintah untuk
mendaftarkan uang.py agar dikenal sebagai modul.
Listing 10.5: DEBIAN/postinst

#!/ b i n / s h

py entral

pkginstall

python uang

Juga python-uang/DEBIAN/prerm.
Listing 10.6: DEBIAN/prerm
1

#!/ b i n / s h

py entral

pkgremove

python uang

Buat keduanya exe utable.


1

sudo

hmod 7 5 5

python uang /DEBIAN/ p o s t i n s t

sudo

hmod 7 5 5

python uang /DEBIAN/ prerm

Pastikan semua le dimiliki root.


1

sudo

hown

root . root

python uang

Lihat lagi apa yang sudah dibuat.


1

python uang /

find

python uang

python uang /DEBIAN

python uang /DEBIAN/ o n t r o l

python uang /DEBIAN/ prerm

python uang /DEBIAN/ o n f f i l e s

python uang /DEBIAN/ p o s t i n s t

python uang / u s r

python uang / u s r / s h a r e

10

python uang / u s r / s h a r e / p y e n t r a l

11

python uang / u s r / s h a r e / p y e n t r a l / python uang

12

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

BAB 10.

13

94

PENGEMASAN

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

/ uang . py
14

python uang / e t

15

python uang / e t / uang . o n f


Kemas.

dpkgdeb :

sudo

dpkgdeb

dpkgdeb :

b u i l d

peringatan :

ontains

python uang

u s e r d e f i n e d

membuat

' python uang /DEBIAN/ o n t r o l '

paket

field

' PythonV e r s i o n '

` python uang '

di

dalam

` . / python

uang_0 . 1 _ a l l . deb ' .


4

dpkgdeb :

peringatan :

ontrol

ignoring

warnings

about

the

file (s)

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.
1

Memilih

sudo

dpkg

( S e d a n g memba a

S e d a n g membuka

paket

telah

Sedang

Pro essing

basis

yang

data

sebelumnya

...213458

tidak

berkas

dan

dipilih .
direktori

terpasang . )

_ a l l . deb )
5

python uang_0 . 1 _ a l l . deb


python uang

paket

python uang

( dari

python uang_0 . 1

...

menyetel

python uang

triggers

for

(0.1)

...

python e n t r a l

...

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
Lalu ujilah di modus interaktif.

Python

python

[GCC 4 . 4 . 3

Type

2.6.5

( r265 : 7 9 0 6 3 ,
on

" help " ,

Apr

16

2010 ,

13:09:56)

linux2

" opyright " ,

" redits"

or

" li ense "

for

more

information .
5

>>> f r o m

>>> uang ( 1 0 0 0 0 )

uang

import

uang

'10.000 '
Ujian terakhir hapuslah paket ini untuk memastikan s ript DEBIAN/prerm
berfungsi dengan baik.

a p t g e t

remove

python uang

S e d a n g memba a

sudo

daftar

paket . . .

Selesai

BAB 10.

Membangun pohon

Memba a

Paket

6
7

ketergantungan

informasi

berikut

yang

tersedia . . .

Selesai

akan DIHAPUS :

python uang
0

dimutakhirkan ,
tidak

95

PENGEMASAN

Setelah

akan

operasi

baru

terinstal ,

akan

dihapus

dan

192

dimutakhirkan .
ini ,

0B r u a n g

kosong

harddisk

akan

digunakan .
9
10

Anda

ingin
telah

11

melanjutkan

( S e d a n g memba a

[ Y/ t ?
data

...213460

berkas

dan

direktori

terpasang . )

S e d a n g membuang

10.2

basis

python uang

...

Debian Repository

Kini saatnya membuat repository agar bisa di-apt-get dari komputer lain. Pasanglah
paket yang dibutuhkan untuk memba a le-le *.deb.
1

sudo

a p t g e t

install

dpkgd e v

Letakkan paketnya di tempat yang sudah ditentukan web server Apa he.
1

sudo

mkdir

sudo

/ v a r /www/ deb

/ u s r / l o a l / s r / python uang_0 . 1 _ a l l . deb

/ v a r /www

/ deb
Lalu buatlah /var/www/deb/update-list.sh. File ini digunakan untuk memperbaharui daftar paket yang tersedia.
Listing 10.7: updatelist.sh
1

rm

dpkgs a n p a k a g e s

Pa kages . gz

gzip

b e s t

a r h

all

>/d e v / n u l l > P a k a g e s

Pa kages

Setiap ada paket baru jalankan le ini.


1

sudo

/ v a r /www/ deb
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.
Listing 10.8: /et /apt/sour es.list.d/ ustom.list
1

deb

h t t p : / / 1 9 2 . 1 6 8 . 0 . 1 / deb

Perbaharui daftar paket.


1

sudo

a p t g e t

update

./

BAB 10.

96

PENGEMASAN

Pasang paket yang dimaksud.


1

sudo

10.3

a p t g e t

install

python uang

Remastering Ubuntu

Untuk semakin memudahkan pemasangan, ada baiknya pasang paket-paket


yang dimaksud ke dalam sebuah le ISO. Bukan hanya memasang, bahkan Anda bisa mengkongurasi se ara manual untuk memastikan pemasangan Linux
Ubuntu dan aplikasi yang dimaksud berlangsung lan ar dan
Mulailah pasang paket yang dibutuhkan.
1

sudo

a p t g e t

install

s q u a s h f s t o o l s

mudah

mkisofs

Buat le onf.


Listing 10.9: remaster/ onf
1

SOURCE=" /home/ s u g i a n a /Unduhan/ b l a n k o n 6.0 d l i v e i 3 8 6 . i s o

TARGET=" b l a n k o n 6.0 d l i v e s o h o i 3 8 6 . i s o "

LABEL=" BlankOn

"
6 SOHO"

Sesuaikanlah ketiganya. Kemudian buat le 1-extra t.sh:


Listing 10.10: remaster/1-extra t.sh
1

mkdir

./ onf

mount

rsyn

p /tmp / drom /tmp / r o o t


o l o o p $SOURCE /tmp / drom
e x l u d e ' f i l e s y s t e m . s q u a s h f s

'

/tmp / drom /

drom /
5

mount

loop

squashfs

squashfs

/tmp / drom / a s p e r / f i l e s y s t e m .

/tmp / r o o t

umount /tmp / r o o t

/tmp / r o o t

umount /tmp / drom


Lalu buat le 2- hroot.sh.
Listing 10.11: remaster/2- hroot.sh

/ et / r e s o l v . onf

hroot

root

mount

hroot

root

mount

hroot

root

rm

hroot

root

a p t g e t

hroot

root

umount

sys

hroot

root

umount

pro

root / et

t
t

pro
sysfs

root / et / r e s o l v . onf
lean

none
none

/ pro
/sys

BAB 10.

97

PENGEMASAN

root

rm

drom / p r o g r a m s

11

hmod +w drom / a s p e r / f i l e s y s t e m . m a n i f e s t

12

hroot

r f

rm

/tmp / *

hroot

10

root

r f

dpkgq u e r y

/ root / . bash_history

W s h o w f o r m a t = ' $ { P a k a g e }

${

V e r s i o n } \n ' > drom / a s p e r / f i l e s y s t e m . m a n i f e s t


13

drom / a s p e r / f i l e s y s t e m . m a n i f e s t

drom / a s p e r /

f i l e s y s t e m . m a n i f e s t d e s k t o p

14

sed

ie

' / u b i q u i t y /d '

drom / a s p e r / f i l e s y s t e m . m a n i f e s t

desktop

Terakhir buat le 3-pa k.sh.


Listing 10.12: remaster/3-pa k.sh
1

rm

awal=` date `

5
6
7

8
9
10
11

./ onf

drom / a s p e r / f i l e s y s t e m . s q u a s h f s

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

drom

find

t y p e f p r i n t 0 | x a r g s 0 md5sum > md5sum . t x t


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 .
noemulb 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 .

mkisofs

e ho
e ho
e ho
e ho

at

" Awal

$awal "

" Akhir

" ` date `

" Sour e

" ` ls

" Target

" ` ls

l
l

$SOURCE |

awk
awk

'{ print

. . / $TARGET |

$5 } ' `

'{ print

$5 } ' `

Jalankan s ript pertama.


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 :/#
Di sini Anda bisa melakukan perubahan sebagaimana biasa. Contoh:

r o o t  l a p t o p :/#

r o o t  l a p t o p :/#

wget

r o o t  l a p t o p :/#

a p t g e t

update

r o o t  l a p t o p :/#

a p t g e t

install

server

squid

/ e t / apt / s o u r e s . l i s t . d
http : / / debian . rab . o . i d / rab . l i s t
internet

s h a r i n g

dh p3

vim

Kalau sudah selesai keluarlah dari hroot dengan menekan Ctrl-D atau ketik
exit:

BAB 10.

98

PENGEMASAN

r o o t  l a p t o p :/#

exit

exit

sugianalaptop :~ $
Root dire tory kini telah berisi aplikasi yang dibutuhkan. Saatnya membuat
iso dengan menjalankan s ript ketiga.

s u d o 3 p a k . s h
Tunggu sekitar 5 menit.

Parallel

mksquashfs :

Creating

4.0

squashfs ,
3

Using

filesystem
blo k

size

on

pro essors

drom / a s p e r / f i l e s y s t e m .

131072.

[==========================|

15063/84258

17%

Terakhir s ript akan memberikan informasi ukuran iso yang dihasilkan berikut
iso aslinya.
1

357433

Awal

Sen Agu

extents

written

Akhir

Sen Agu 2

Sour e

731869184

Target

732022784

( 6 9 8 MB)

0 9 : 4 5 : 3 9 WIT 2 0 1 0
0 9 : 5 0 : 5 2 WIT 2 0 1 0

Jika media yang Anda tuju nanti adalah CDROM, pastikan ukurannya
dibawah 700MB. Lebih mudahnya bandingkan dengan ukuran ISO aslinya. Pada 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

Setelah selesai jalankan lagi s ript ketiga:


1

sudo

s h 3 p a k . s h

File ISO yang dihasilkan bisa Anda oba terlebih dahulu di VirtualBox .
Anda juga bisa memasangnya di ashdisk menggunakan usb- reator-gtk. Jika
sudah yakin barulah membakarnya (burn) ke CD-ROM.

1 virtualbox.org

Bab 11

Graphi al User Interfa e


Bab-bab sebelumnya kita mempelajari bagaimana membuat aplikasi dalam lingkungan teks (text mode), beberapa menyebutnya lingkungan konsole. Contohnya
fungsi raw_input() yang meminta masukan user dari konsole. Lingkungan yang
dimaksud ber irikan tidak membutuhkan mouse, ukup dengan keyboard saja
sebagai alat masukan (input devi e).
Kali ini kita masuk pemrograman berbasis gras dimana mouse bisa digunakan sebagai alat masukan untuk klik tombol, opy paste, dsb. Graphi al Uset
Interfa e (GUI) tidaklah wajib di Python, ia hanya sebagai modul.

Berbeda

dengan Visual Basi atau Borland Delphi yang mewajibkan GUI.


Modul berbasis GUI tidak hanya satu di Python, ada Qt, Wx, GTk, T l, dst.
Di sini kita akan membahas Qt sebagai pustaka antarmuka gras. Pasanglah
paketnya.
1

sudo

a p t g e t

install

python q t 4

Juga dokumentasinya, meski tidak wajib.


1

sudo

a p t g e t

install

q t 4 do h t m l

Seperti biasa, mulailah dari yang sederhana, yaitu membuat aplikasi Hello
world dalam le hello.py.

1
2
3
4
5
6
7
8

import
from
from
lass
def

Listing 11.1: hello.py


sys

PyQt4

import

PyQt4 . QtGui

Qt

import

FormUtama ( QMainWindow) :
__init__ ( s e l f ) :
QMainWindow . __init__ ( s e l f )
s e l f . setWindowTitle ( ' Hello

9
10

99

world ' )

BAB 11.

GRAPHICAL USER INTERFACE

100

Gambar 11.1: Hello world

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
14

fm . show ( )

#app . exe _ ( )
Butuh tampilan penuh ? Gantilah

fm.show()
menjadi

fm.showMaximized()
11.1

Orientasi Objek

Di sini teknik pemrograman semakin terstruktur dimana pemrograman berorientasi objek (Obje t Oriented Programming / OOP) diterapkan.

Mari kita

rin i lagi pembahasan sour e hello.py tersebut.


Class bisa dianggap sebuah tipe data, disejajarkan dengan tipe string, integer, oat, list, di tionary, datetime, dst. Dengan demikian FormUtama merupakan tipe data. Perhatikan baris 5

lass FormUtama(QMainWindow):
itu artinya FormUtama merupakan turunan (inheritan e) dari lass QMainWindow.

Itu artinya variabel dan fungsi yang dimiliki lass QMainWindow

juga dimiliki oleh lass FormUtama. Bahasa lainnya FormUtama mewarisi sifat
QMainWindow.
Selanjutnya ada fungsi __init__().

Fungsi ini merupakan fungsi khusus

yang dijalankan saat pembentukan sehingga disebut sebagai onstru tor. Saat
pembentukan ? Ya, perhatikan baris 12

fm = FormUtama()
Itu adalah pembentukan variabel fm yang bertipe FormUtama. Disinilah fungsi
__init__() dipanggil.

BAB 11.

GRAPHICAL USER INTERFACE

101

Dalam istilah OOP, fm disebut sebagai instan e atau variabel bertipe


lass. Namun di Python rasanya semua tipe data adalah lass. Misalnya tipe string. Ia tidak hanya memuat data seperti 'ab d' saja,
melainkan juga memuat fungsi seperti repla e(), rjust(), dst. Hal ini
bisa dibuktikan dengan print dir('ab d'). Sehingga boleh dikatakan
di Python semua variabel adalah objek. Bagi programmer PHP Anda bisa ermati bahwa string 'ab d' hanya sekedar data.
Sekarang perhatikan baris 7

QMainWindow.__init__(self)
Fungsi __init__() yang dimiliki QMainWindow perlu dipanggil lagi. Mengapa
? Karena FormUtama mendenisikan ulang fungsi __init__().
Lalu apa itu self ? self adalah variabel yang mewakili FormUtama itu sendiri.
Setiap fungsi yang dimiliki oleh suatu lass setidaknya memiliki satu masukan
(input parameter) yaitu self.
Selanjutnya lihat baris 13

fm.show()
dimana kita tidak pernah mendenisikan fungsi show() di dalam lass FormUtama. 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

app = Qt.QAppli ation(sys.argv)


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.

11.2

Daftar Pegawai

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.

1
2
3
4
5
6
7
8
9

import
from
from
from
lass
def

102

GRAPHICAL USER INTERFACE

Listing 11.2: gui/pegawai.py


sys

PyQt4

import

PyQt4 . QtGui

PyQt4 . QtCore

Qt

import *
import

QDate ,

SIGNAL

FormUtama ( QMainWindow) :
__init__ ( s e l f ) :
QMainWindow . __init__ ( s e l f )
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

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

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

24

s e l f . l a b e l J e n i s . setText ( ' Jenis

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 ( ' ddMM
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

= QLabel ( s e l f )

= QTableWidget ( s e l f )

' ID ' , ' Nama ' , ' Alamat ' , ' T g l

Lahir ' )
Kelamin ' )

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.

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 ,
') ,

48
49
50

def

103

GRAPHICAL USER INTERFACE

SIGNAL ( ' l i k e d ( )

s e l f . simpan )

simpan ( s e l f ) :
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 (

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 (

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 (

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 (

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 (

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 ( )

s t r ( pid ) ) )
s e l f . editNama . t e x t ( ) ) )
s e l f . editAlamat . toPlainText ( ) ) )
s e l f . editTglLahir . text () ) )
s e l f . e d i t J e n i s . urrentText ( ) ) )

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 _ ( )
Bagaimana, panjang bukan ?
Ya, ontoh kali ini menyertakan lass yang kerap digunakan.

Berikut ini

ulasan masing-masing lass tersebut.

QLabel
QLineEdit
QTextEdit
QDateEdit
QComboBox
QPushButton

Menampilkan tulisan saja, tidak bisa diedit user.


Untuk memasukkan tulisan, satu baris saja.
Untuk memasukkan tulisan juga, tapi bisa lebih dari satu baris.
Untuk mengisi tanggal.
Untuk menetapkan pilihan.
Tombol yang bila di-klik menjalankan suatu fungsi. Dalam hal

ini menyimpan data pegawai ke QTableWidget yang ada di bawahnya.

QTableWidget

Menampilkan data berbentuk tabel.

BAB 11.

GRAPHICAL USER INTERFACE

Gambar 11.2: Daftar Pegawai

104

BAB 11.

GRAPHICAL USER INTERFACE

105

Dari sour e tersebut dan menganalisa tampilan form, rasanya Anda bisa memahami ara penggunaan lass di atas.
Untuk mengetahui lass lainnya beserta fungsi yang ada di dalamnya Anda bisa lihat di /usr/share/qt4/do /html/ lasses.html. Gunakanlah browser untuk melihatnya.

Bab 12

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 pembuatan objek. Mari mulai pada kasus.
Ada sebuah le teks bernama barang.txt dengan isi seperti berikut ini.
Listing 12.1: barang.txt
1

1 Jeruk

2 Mangga

3 Pisang

34

9000

10000

8000

Pembuat le itu memastikan data barang tersimpan dengan

tetap

lebar kolom

. 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 langkahlangkah 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

Mulailah membuat s ript barang1.py.

1
2

Listing 12.2: barang1.py

import

sys

f i l e n a m e = sys . argv [ 1

for

5
6

f = open ( f i l e n a m e )

in

line

f . readlines () :

kode = l i n e [ : 3 . s t r i p ( )

nama = l i n e [ 3 : 3 + 1 0 . s t r i p ( )

stok = l i n e [3+10:3+10+2. s t r i p ( )

harga = l i n e [3+10+2:. s t r i p ( )

print

10
11

[ kode ,

nama ,

stok ,

harga

f . lose ()

Jalankan.
1

[ '1 ' ,

python

' Jeruk ' ,

b a r a n g 1 . py

[ '2 ' ,

' Mangga ' ,

' ' ,

[ '3 ' ,

' Pisang ' ,

'7 ' ,

barang . t x t

'34 ' ,

'9000 '
'8000 '
'10000 '

Tahap ini sudah baik, dimana setiap nilai sudah dapat diwakili dalam variabel kode, nama, stok, dan harga. Namun barang1.py masih kurang modular
karena masukannya berupa nama le yang diberikan melalui ommand line.

12.1

Lebih Terstruktur

Kita perlu meningkatkan kadar modularitas dengan membuat fungsi. Buatlah


barang2.py berikut.

1
2

def

Listing 12.3: barang2.py


barang ( f i l e n a m e ) :
f = open ( f i l e n a m e )
rows =

for

4
5
6

line

in

f . readlines () :

kode = l i n e [ : 3 . s t r i p ( )
nama = l i n e [ 3 : 3 + 1 0 . s t r i p ( )

stok = l i n e [3+10:3+10+2. s t r i p ( )

harga = l i n e [3+10+2:. s t r i p ( )

row = [ kode , nama , s t o k , h a r g a

10

r o w s . append ( row )

11

f . lose ()

return

12
13
14
15

if

rows

__name__ ==

'__main__ ' :

BAB 12.

OBJECT ORIENTED PROGRAMMING

import
for
in
print

16

108

sys

17

f i l e n a m e = sys . argv [ 1

18

row

19

barang ( f i l e n a m e ) :
row

Jalankan.
1

[ '1 ' ,

python

' Jeruk ' ,

b a r a n g 2 . py

[ '2 ' ,

' Mangga ' ,

' ' ,

[ '3 ' ,

' Pisang ' ,

'7 ' ,

'34 ' ,

barang . t x t
'9000 '
'8000 '
'10000 '

Hasil tetap sama, namun kini s ript tidak hanya mengandung fungsi tetapi
juga bisa digunakan sebagai modul.

12.2

Lebih Umum

Sekarang aspek generalitas, atau tingkat ke-umum-an fungsi, dimana lebar setiap 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

kolom memiliki lebar tertentu

setiap

. 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.

1
2

def

Listing 12.4: xtable.py


f i x t a b l e ( filename ,
rows =

for

4
5
6

line

in

for

f . readlines () :

awal = 0
row =

widths ) :

f = open ( f i l e n a m e )

width
field

10

in

widths :

a k h i r = awal + width
= l i n e [ awal : a k h i r . s t r i p ( )

row . append ( f i e l d )

11

awal = a k h i r

12

r o w s . append ( row )

13

f . lose ()

return

14
15
16
17

if

rows

__name__ ==

'__main__ ' :

BAB 12.

import
for
in
print

18

109

OBJECT ORIENTED PROGRAMMING

sys

19

f i l e n a m e = sys . argv [ 1

20

row

21

f i x t a b l e ( filename ,

[3 ,10 ,2 ,8) :

row

Jalankan.
1

[ '1 ' ,

python

' Jeruk ' ,

f i x t a b l e . py

[ '2 ' ,

' Mangga ' ,

' ' ,

[ '3 ' ,

' Pisang ' ,

'7 ' ,

barang . t x t

'34 ' ,

'9000 '
'8000 '
'10000 '

Perhatikan lagi, hasil masih sama.

Anda bisa uji dengan membuat pe-

gawai.txt.
Listing 12.5: pegawai.txt
1

1BUMMI DWI PUTERA,

2ARIEF SETIADI

ST

1985 08 17L

3CECEP ZAHRUDIN ,

4NITA PANDRIA

1976 09 19P

5ILHAM

1984 11 05L

6MIRANDA

1978 10 01P

1972 05 02L
ST

1972 06 01L

Lalu xpegawai.py.

1
2
3

Listing 12.6: xpegawai.py

from
import

fixtable
sys

import

fixtable

f i l e n a m e = sys . argv [ 1

for

6
7

in
print

row

f i x t a b l e ( filename ,

[2 ,22 ,10 ,1) :

row

Jalankan.
1

[ '1 ' ,

python

'BUMMI DWI PUTERA,

f i x p e g a w a i . py

pegawai . t x t

[ '2 ' ,

' ARIEF SETIADI ' ,

[ '3 ' ,

'CECEP ZAHRUDIN ,

[ '4 ' ,

' NITA PANDRIA' ,

[ '5 ' ,

'ILHAM' ,

[ '6 ' ,

'MIRANDA' ,

ST ' ,

'1985 08 17 ' ,

'1972 05 02 ' ,
ST ' ,

'1972 06 01 ' ,

'1976 09 19 ' ,

'1984 11 05 ' ,

'L '

'L '
'L '

'P '

'L '

'1978 10 01 ' ,

'P '

Fungsi xtable teruji.

12.3

Tingkat Kerumitan

Kompleksitas masalah kian bertambah.

memperhatikan tipe data

Kini Anda membutuhkan hasil yang

. Perhatikan lagi barang.txt dimana:

BAB 12.

OBJECT ORIENTED PROGRAMMING

kolom pertama, kode barang, bertipe integer

kolom kedua, nama barang, bertipe string

kolom ketiga, stok, bertipe integer

kolom keempat, harga, bertipe integer

110

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.

1
2
3
4
5

from
def

types

f i x t a b l e ( filename ,

for

8
9

line

for

11
12

in

ftypes ) :

f . readlines () :

width ,

ftype

field

14

field :
= None

f t y p e == I n t T y p e :

16

field

17

= int ( f i e ld )

row . append ( f i e l d )

18

awal = a k h i r

19

r o w s . append ( row )

20

f . lose ()

return

21
22
24
25
26
27

ftypes :

= l i n e [ awal : a k h i r . s t r i p ( )

field

15

in

a k h i r = awal + width

if not
elif

13

23

StringType

awal = 0
row =

10

IntType ,

f = open ( f i l e n a m e )
rows =

import

Listing 12.7: FixTableType.py

if

rows

__name__ ==

import

'__main__ ' :

sys

f i l e n a m e = sys . argv [ 1
fields

= [

28

[ 3 , IntType ,

29

[ 1 0 , StringType ,

30

[ 2 , IntType ,

31

[ 8 , IntType

32

BAB 12.

OBJECT ORIENTED PROGRAMMING

for

33
34

in
print

row

f i x t a b l e ( filename ,

111

fields ) :

row

Jalankan.
1

[1 ,

python

' Jeruk ' ,

F i x T a b l e T y p e . py

[2 ,

' Mangga ' ,

None ,

[3 ,

' Pisang ' ,

7,

34 ,

barang . t x t

9000
8000

10000

Perhatikan, tidak ada lagi kutip di kolom pertama, ketiga, dan keempat.
Selanjutnya ada kebutuhan untuk menyimpan kembali data tersebut ke sebuah 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

Mengirim SMS 1 selama 10 detik

Mengabari status SMS 1 selama 5 detik

Mengirim SMS 2 selama 10 detik

Mengirim status SMS 2 selama 5 detik

Total waktu yang dibutuhkan untuk mengirim dua SMS adalah 30 detik.
Sekarang bandingkan bila menggunakan multi-thread.
Saat

Thread 1

Thread 2

Mengirim SMS 1 10 detik

Mengirim SMS 2 10 detik

Mengabari status SMS 1 5 detik

Mengabari status SMS 2 5 detik

Total waktu yang dibutuhkan adalah 10+10+5 = 25 detik, selisih 5 detik


dari single-thread. Bagi SMS gateway itu merupakan jeda yang ukup berarti
mengingat banyaknya SMS yang dikirim.
Mari kita mulai simulasinya dengan membuat test_thread.py.

from

Listing 13.1: testthread.py

threading

import

Thread

112

BAB 13.

2
3
4
5
6
7
8
9

import
import
from

113

KERJA SAMPINGAN

time
os

glob

lass
def

import

glob

K i r i m ( Thread ) :
__init__ ( s e l f ,

k) :

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
14

def

run ( s e l f ) :

print
while
if not
ontinue
del
#s e l f . kabar =
print

t i m e . s t r f t i m e ( '%H:%M:%S ' ) ,

dimulai

15

time . s l e e p ( 1 )

17

s e l f . kabar :

18
19

hasil =

20

s e l f . kabar [ 0

s e l f . kabar [ 0

21
22

25

s e l f . kabar [ 1 :

'%s KABARI %s ' % ( t i m e . s t r f t i m e ( '%H:%M

:%S ' ) ,

24

sampingan

s e l f . kerja :

16

23

' Kerja

'

def

26

hasil )

join ( sel f ) :

print

' Kerja

sampingan

berakhir '

s e l f . kerja = False

27

Thread . j o i n ( s e l f )

28
29
30

job_dir =

31

kabar =

' /tmp / j o b '

32
33

sampingan = Kirim ( kabar )

34

sampingan . s t a r t ( )

35

print
while
if not
ontinue
if not
ontinue

36

t i m e . s t r f t i m e ( '%H:%M:%S ' ) ,

' Pekerjaan

'

37
38
39
40
41
42
43
44

True :

time . s l e e p ( 1 )
os . path . e x i s t s ( job_dir ) :

filenames

= g l o b ( '%s / * ' % j o b _ d i r )

filenames :

filename = filenames [ 0

utama

dimulai

BAB 13.

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 )

print

49

114

KERJA SAMPINGAN

'%s KERJAKAN %s ' % ( t i m e . s t r f t i m e ( '%H:%M:%S ' ) ,

job )

50
51
52
53

k a b a r . append ( j o b )

print

' Pekerjaan

utama

berakhir '

sampingan . j o i n ( )
Jalankan.

04:56:54

python

Pekerjaan

t e s t t h r e a d . py

04:56:54

Kerja

utama

dimulai

sampingan

dimulai

Sampai di sini ia menunggu keberadaan le di direktori /tmp/job.

Buka

konsole lain dan buatlah direktori /tmp/job.


1

mkdir

/tmp / j o b

Lalu buatlah le apa saja.


1

e ho

h e l l o > /tmp / j o b / h e l l o . t x t

Kemudian lihat konsole testthread.py tadi.


1

0 4 : 5 6 : 5 6 KERJAKAN

04:56:57

KABARI

hello

hello

Pointer
Perlu diperhatikan variabel kabar yang bertipe list (baris 30). Ini adalah

abel bersama

vari-

, 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

s e l f . kabar = k
adalah

del

sama

. Perhatikan juga penghapusan antrian pertama di baris 20

s e l f . kabar [ 0

dimana pada program biasa bisa saja Anda membuatnya menjadi


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

a p t g e t

sudo

install

imgw

Proses instalasi akan meminta Anda menyesuaikan le /et /im/gw/ ong.py.

File ini perlu diisi dengan otentikasi ke database yang sudah dibuat

tadi.
1

db_url =

' p o s t g r e s : / / ilham :1234 lo alhost :5432/ t o t a l i n d o '

Kemudian jalankan:
1

sudo

dpkg r e o n f i g u r e

imgw

Proses ini akan membuat tabel yang dibutuhkan ke database totalindo.


Paket im-gw digunakan untuk hal yang berkaitan dengan database seperti
menyimpan dan mengirim pesan. Daemonnya bisa Anda stop dan start dengan
ara:
1

sudo

/ e t / i n i t . d / imgw

restart

im-gw juga otomatis hidup saat komputer dihidupkan. Anda bisa memantau
log-nya dengan ara:
1

2011 01 18

sudo

tail

/ v a r / l o g / im /gw . l o g

05:12:20 ,883

INFO

Start

result

dir

/ var / s p o o l /

INFO

Start

job

pid

1202

im / r e s u l t /
3

2011 01 18

05:12:20 ,886

115

at

BAB 14.

2011 01 18
on

116

SMS GATEWAY

05:12:20 ,928

port

INFO

Start

result

xmlrp

server

9317

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 pengendali modem:
1

sudo

a p t g e t

install

immodem

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

5627

28464

g r e p modem

? SN

0:06

/ u s r / b i n / python

0:01

python

Sl

/ u s r / b i n /modemh o t p l u g

/ u s r / b i n /modem / d e v / ttyUSB0

Perhatikan /usr/bin/modem-hotplug, dialah yang memantau aktivitas pemasangan perangkat USB. Lalu ada juga /usr/bin/modem, daemon inilah yang
dipanggil oleh modem-hotplug saat USB modem ditan apkan. Lalu bagaimana
jika perangkatnya ditan apkan di serial port ?
Anda pastikan dulu modem itu terpasang di serial port berapa. Keberadaan
serial port bisa dilihat dengan perintah berikut:
1

dmesg

25.972197
a

grep

ttyS

serial8250 :

ttyS0

at

I /O 0 x 3 f 8

( i r q = 4)

is

1 6 5 5 0A

25.973141

00:07:

ttyS0

at

I /O 0 x 3 f 8

( i r q = 4)

is

1 6 5 5 0A
4

42.442528
is

[
[
[

a
a

at

I /O 0 x d 1 0 0

( i r q = 17)

0000:05:01.0:

ttyS5

at

I /O 0 x d 2 0 0

( i r q = 17)

0000:05:02.0:

ttyS6

at

I /O 0 x d 7 0 0

( i r q = 19)

ttyS7

at

I /O 0 x d 8 0 0

( i r q = 19)

1 6 5 5 0A

42.538574
is

ttyS4

1 6 5 5 0A

42.538359
is

0000:05:01.0:

1 6 5 5 0A

42.442750
is

0000:05:02.0:

1 6 5 5 0A

Anda bisa menyebutkan semua serial port yang ada pada le /et /im/modem/modem. onf:
1

[ devi e

p o r t = USB0 USB1 USB2 USB3 USB4 USB5 USB6 USB7 S0

devi e
S6

di

/ dev / t t y

S7

Lalu restart semua modem:

S4

S5

BAB 14.

sudo

117

SMS GATEWAY

/ e t / i n i t . d /modem

restart

Tunggu sekitar 30 detik, lalu jalankan


1

11211

ps

ax

g r e p modem

Rl

10:29

python

/ u s r / b i n /modem / d e v /

ttyS0
untuk mengetahui serial port mana yg digunakan. Anda bisa mengesienkan
modem. onf diatas dengan hanya men antumkan S0 saja, namun tidak diubah
pun tidak menjadi masalah.
Sedangkan untuk melihat log-nya, terlebih dahulu Anda periksa direktori
/var/log/modem, ada le apa di sana:
1

510012541218911. l o g

sudo

ls

/ v a r / l o g /modem

Selanjutnya mulailah memantau:


1

2011 01 18

sudo

tail

01:45:22 ,304

/ v a r / l o g /modem/ 5 1 0 0 1 2 5 4 1 2 1 8 9 1 1 . l o g
INFO

2011 01 18

01:45:24 ,307

INFO

2011 01 18

01:45:24 ,308

INFO

2011 01 18

01:45:24 ,308

INFO

2011 01 18

01:45:24 ,309

INFO

2011 01 18

01:45:26 ,312

INFO

2011 01 18

01:45:26 ,312

INFO

>
<
<
<
>
<
<
>
<
<
<
>
<
<
>
<
<
>
<
<

30

AT+CSQ
AT+CSQ
+CSQ :

20 ,0

OK
AT+CLIP=1
AT+CLIP=1
OK

2011 01 18

01:45:26 ,312

INFO

10

2011 01 18

01:45:27 ,326

INFO

AT+CGMM

11

2011 01 18

01:45:27 ,326

INFO

12

2011 01 18

01:45:27 ,327

INFO

13

2011 01 18

01:45:27 ,327

INFO

14

2011 01 18

01:45:29 ,330

INFO

15

2011 01 18

01:45:29 ,330

INFO

16

2011 01 18

01:45:29 ,330

INFO

17

2011 01 18

01:45:31 ,332

INFO

18

2011 01 18

01:45:31 ,333

INFO

19

2011 01 18

01:45:31 ,333

INFO

20

2011 01 18

01:45:32 ,346

INFO

21

2011 01 18

01:45:32 ,346

INFO

22

2011 01 18

01:45:32 ,352

INFO S e r v i n g

AT+CGMM
MULTIBAND

9 0 0E

1800

OK
AT+CNMI= 0 , 1 , 1 , 1 , 0
AT+CNMI= 0 , 1 , 1 , 1 , 0
OK
AT+CMGF=1
AT+CMGF=1
OK
AT+CMGL="ALL"
AT+CMGL="ALL"
OK
/ d e v / ttyUSB1

v a r / s p o o l / im / j o b /modem/ 5 1 0 0 1 2 5 4 1 2 1 8 9 1 1 /

at

pid

and

28464

Bila Anda sudah berjumpa kalimat yang berawalan Serving seperti di atas,
maka modem sudah siap.

14.1.1 IMEI Chip


Lalu apa yang dimaksud dengan angka 510012541218911 pada nama le log ?

Mengapa tidak USB0.log atau S0.log saja ?

BAB 14.

118

SMS GATEWAY

Angka itu disebut dengan IMEI alias identitas hip / SIM ard. Jika komputer 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 tersebut di tabel im.agent. Kalau belum ada ia tambahkan, dan kalau sudah ada ia
perbaharui statusnya.
1

Password

psql

ilham
for

user

lo alhost

psql

SSL

Type

(8.4.4)

t o t a l i n d o=> SELECT i d ,

onne tion
" help "

7
8
9
10

totalindo

ilham :

( ipher :

for

DHERSAAES256SHA,

bits :

256)

help .

id

s t a t u s FROM im . a g e n t ;

status

+
510012541218911
(1

row )
Status 0 berarti modem siap, status negatif berarti sebaliknya. Alasan untuk

status negatif bisa Anda lihat di tabel im.status.

14.2

Hello world!

Mari mulai mengirim SMS ke handphone Anda, masih di psql.


1

t o t a l i n d o=> INSERT INTO im . a n t r i a n ( p e n e r i m a , p e s a n )

t o t a l i n d o > SELECT

INSERT 0

'+628179140068 ' , ' Hello

world ! ' ;

Untuk penerima sesuaikanlah dengan nomor handphone Anda.


Status pengiriman bisa Anda lihat di tabel im.selesai.
1

t o t a l i n d o=> SELECT i d ,

t o t a l i n d o > FROM im . s e l e s a i

id

status

pesan

status ,

pengirim ,

penerima ,

ORDER BY 1 DESC LIMIT

pengirim

penerima

pesan
1;

BAB 14.

4
5

119

SMS GATEWAY

++++
1065

510012541218911

+628179140068

Hello

world !
6

(1

row )
Status 0 berarti telah terkirim, negatif sebaliknya, sedangkan positif berarti

sedang diproses. Penjelasannya bisa dilihat di tabel im.status.


Setelah Anda menerima SMS di handphone, balaslah SMS itu dengan:

Diterima
Tunggu sekitar 30 detik, dan lihat tabel im.antrian.
1

t o t a l i n d o=> SELECT i d ,

t o t a l i n d o > FROM im . a n t r i a n ;

3
4
5

id

kirim

kirim ,

pengirim

pengirim ,
|

penerima ,

penerima

pesan

pesan

++++
1071

+628179140068

510012541218911

Diterima
6

(1

row
Mungkin Anda bertanya-tanya, saat mengirim pesan tabel im.antrian yang

digunakan, begitu juga saat menerima pesan. Lalu apa pembedanya ?


Perhatikan eld kirim di atas. Jika eld kirim = f (False), itu berarti re ord
pesan masuk.

Jika bernilai t (True) berarti pengiriman pesan.

Defaultnya

adalah True (pengiriman pesan).

14.3

Instant Messenger Gateway

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.

14.3.1 Yahoo! Messenger


Sebelum pemasangan, sebaiknya Anda siapkan Yahoo! a ount yang baru yang
akan digunakan oleh /usr/bin/ym (daemon dari paket im-ym).
pasang paketnya.

Selanjutnya

BAB 14.

SMS GATEWAY

Gambar 14.1: Alur IM gateway

120

BAB 14.

sudo

121

SMS GATEWAY

a p t g e t

install

imym

Kemudian sesuaikan /et /im/ym/ ong.py, seperti ontoh berikut:


1

users = { ' inforab ' :

' 1234 ' }

dimana inforab adalah Yahoo! a ount dan 1234 adalah passwordnya.


Setelah disimpan tunggu satu menit dan periksa keberadaannya.
1

2339

ps

ax

g r e p ym

Sl

24:44

python

/ u s r / b i n /ym i n f o r a b

Log-nya juga tersedia.


1

2011 02 25

sudo

tail

/ v a r / l o g /ym/ i n f o r a b . l o g

14:24:46 ,729

INFO S t a r t u p

{ ' status ' :

0}

Sekarang oba add buddy dari Yahoo! Messenger lient seperti Pidgin. Tentu 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:
1

2011 02 25

15:10:43 ,885

'2011 02 25
pengirim ' :

INFO I n b o x

15:10:43+7 ' ,

{ ' tgl_operator ' :

' pesan ' :

' hello

world ' ,

'

' info_rab ' }

dan lihat juga tabel im.antrian.


1

t o t a l i n d o=> SELECT i d ,

kirim ,

jalur ,

pengirim ,

penerima ,

pesan
2

t o t a l i n d o > FROM im . a n t r i a n ;

3
4

id

5
6

kirim

jalur

pengirim

penerima

pesan

+++++
2074
(1

info_rab

inforab

hello

world

row )
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 dapat saling mengirim pesan.
Jika Anda berminat menggunakan XMPP untuk hatting dengan server,
pasang paket im-xmpp.
1

sudo

a p t g e t

install

imxmpp

Lalu sesuaikan /et /im/xmpp/ ong.py.

BAB 14.

122

SMS GATEWAY

u s e r s = { ' i n f o r a b  g m a i l . om ' :

{ ' password ' :

' port ' :

' 1234 ' ,

5223 ,

' sasl ' :

' server ' :

True ,

' t a l k . g o o g l e . om ' }

}
Sesuaikan inforab dan 1234.

Setelah disimpan tunggu satu menit hingga

daemon-nya up. Setelah hidup, Anda bisa lakukan pengujian yang serupa seperti 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 ' :

{ ' password ' :

' port ' :

' 1234 ' ,

5223 ,

' sasl ' :

' server ' :

' i n f o  j a b b e r . rab . o . i d ' :

True ,

' t a l k . g o o g l e . om ' } ,
' 1234 '

}
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.

14.4

Broad ast

Anda telah memiliki banyak pelanggan dan ingin mengirim pesan yang sama
ke mereka. Dengan mudah lakukan query berikut.
1

INSERT INTO im . a n t r i a n ( p e n e r i m a ,

SELECT no_hp ,

' Selamat

pesan )

t r a n s a k s i ' FROM p e l a n g g a n ;

Sayangnya untuk jumlah penerima yang sangat banyak tidak bisa semudah
itu, karena /usr/bin/modem memiliki nilai job timeout yang default-nya 420 detik 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 solusi, namun tidak disarankan. Teknik yang paling pas adalah menyiapkan daemon 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.
1

sudo

a p t g e t

install

im b r o a d a s t

Untuk mengirim pesan kita perlu melakukan INSERT ke dua tabel, yaitu
im.broad ast dan im.broad ast_penerima. Tabel pertama berisi pesan, sedangkan 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.

t o t a l i n d o=> SELECT

nextval

4
5

123

SMS GATEWAY

n e x t v a l ( ' im . b r o a d a s t _ i d _ s e q ' ) ;

8
(1

row )
Kemudian tambahkan pesannya.

t o t a l i n d o=> INSERT INTO im . b r o a d a s t ( i d , j u d u l , p e s a n )

t o t a l i n d o > SELECT

8,

' Uji

broad ast ' ,

' Selamat

transaksi

';
3

INSERT 0

Field judul hanya untuk keterangan saja. Field pesan-lah yang nanti akan
dikirim. Berikutnya tambahkan penerima pesan.
1

t o t a l i n d o=> INSERT INTO im . b r o a d a s t _ p e n e r i m a ( i d ,

t o t a l i n d o > SELECT

INSERT 0

penerima )
8,

'+628179140068 ';

Jalur default yang digunakan adalah 1 (modem). Untuk jalur lainnya sertakan eld jalur.
1

t o t a l i n d o=> INSERT INTO im . b r o a d a s t _ p e n e r i m a ( i d , p e n e r i m a

t o t a l i n d o > SELECT

INSERT 0

, jalur )
8 , ' info_rab ' , 5 ;

Dimana jalur 5 adalah ym.

Bab 15

Web
15.1

Django

15.2

Webpy

124

Bab 16

Hosting
16.1

Virtualmin

Ingin berbisnis web hosting ? Terbentur biaya untuk pengadaan CPanel ? Saat-

nya menggunakan Virtualmin . Ingin membidik pangsa developer Python selain 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 aplikasi tersebut.

16.1.1 Pemasangan Ubuntu


Ya, kita akan gunakan Ubuntu

2 di sini. Kebiasaan Virtualmin adalah meng-

gunakan Ubuntu jenis LTS (Long Term Support), seperti Hardy (8.04) atau
Lu id (10.04). Kali ini kita akan gunakan versi 10.04 dimana Anda bisa pilih
untuk prosesor 32 bit (i386) atau 64 bit (amd64). Paling aman gunakan i386,
tapi prosesor terbaru rata-rata sudah mendukung versi amd64, bahkan yang
dikeluarkan Intel sekalipun.
Oh iya, ada lagi pengkategorian lainnya, yaitu versi desktop atau server. Jika
server sering berada di depan Anda - misalkan server ada di rumah - sebaiknya

pilih yang desktop, karena telah dilengkapi GUI , sehingga Firefox tersedia.
Namun jika server diletakkan nun jauh di sana, pilihlah versi server agar Anda
tidak berlama-lama saat melakukan upgrade.

1 http://virtualmin. om
2 http://ubuntu. om
3 Graphi al User Interfa e
125

BAB 16.

126

HOSTING

Amannya pilih yang mana ? Pilihlah Ubuntu 10.04 i386 Desktop Edition .
ISO bisa di-burn ke CD-ROM 700 MB. Rata-rata motherboard sekarang sudah 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 Indonesia 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.

$ hmod 750 /home/sugiana


Anda tidak perlu melakukan ini jika membuat user baru melalui Virtualmin
nanti.

16.1.2 Kongurasi Network


Untuk menetapkan IP, Anda bisa menggunakan menu System, Preferen es, Network Conne tions. Jika Anda tidak memasang GUI, bisa lakukan kongurasi
melalui le /et /network/interfa es seperti ini:
1

ifa e

address

eth0

202.59.201.67

inet

stati

netmask

255.255.255.192

gateway

203.130.231.65

Lalu reboot server untuk memastikan kongurasi dijalankan saat server


hidup. Kemudian ujilah dengan mengunjungi salah satu IP yang Anda kenal:

$ 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
Lalu ujilah DNS ini dengan memanggil nama:

4 http://openstorage.gunadarma.a .id/linux/iso/ubuntu/lu id/ubuntu-10.04-desktopi386.iso

BAB 16.

127

HOSTING

$ 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 diset 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).

16.1.3 Pemasangan Virtualmin


Sudah terhubung ke Internet ? Selanjutnya unduh s ript instalasinya:

$ wget http://software.virtualmin. om/gpl/s ripts/install.sh


Lalu jalankan:

$ sudo sh install.sh
Saat ia menanyakan hostname, jawablah sesuai nama domain hosting yang Anda
kelola:
Please enter a fully qualied hostname (for example, example. om):

sabilawebhosting. om

Lalu saat ia menanyakan network interfa e, periksalah di konsole lain dengan


if ong, interfa e apa yang digunakan. Kalau terhubung dengan kabel biasanya
eth0, kalau wireless biasanya wlan0:
Please enter the name of your primary network interfa e:

eth0

Selanjutnya ia mengunduh aplikasi yang diperlukan dan melakuan kongurasi.


Tunggulah, ini memerlukan waktu beberapa lama.

Jika berhasil, pesan ter-

akhirnya adalah:
INFO - Rule updates done
Namun ada kalanya Anda mendapatkan pesan ini:
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.

128

HOSTING

16.1.4 Text Editor


Jika Anda menggunakan GUI, gedit bisa digunakan untuk text editor:

$ 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 kenyamanan:

$ sudo apt-get install vim


Lalu sesuaikan beberapa kongurasi pada

/et /vim/vimr .

Kongurasi berikut

ini untuk mengingat posisi kursor pada le yang pernah Anda buka:
1

" Un omment

the

position
2

"

if

reopening

to

h a v e Vim jump

to

the

last

file

h a s ( " auto md " )


au

BufReadPost
l i n e (" $ ")

following

when

if

exe

l i n e ( " ' \ " " ) > 1 && l i n e ( " ' \ " " ) <=
" normal !

g '\""

endif

endif
Terkait dengan penulisan sour e, pastikan auto-indent bekerja.

Gunakan

karakter spasi untuk indent ketimbang karakter tab:


1

" Un omment
rules

"

if

the

and

a ording

following

to

h a v e Vim

load

indentation

plugins

to

the

dete ted

filetype .

h a s ( " auto md " )

filetype

set

smartindent

plugin

indent

set

expandtab

set

t a b s t o p=4

set

s o f t t a b s t o p =4

set

s h i f t w i d t h =4

10

endif

on

Aktifkan pen arian pintar dimana kalau Anda menuliskan huruf ke il semua
saat pen arian maka tidak mempedulikan huruf ke il ataupun besar (in asesensitive).

Namun jika Anda menyertakan huruf besar maka ase-sensitive

berlaku.
1

set

ignore ase

set

smart ase

" Do

ase

" Do s m a r t

Selesai dan simpanlah.

insensitive
ase

mat hing

mat hing

Kongurasi ini se ara otomatis juga berlaku bagi

user Anda nantinya. Sehingga kenyamanan programmer makin bertambah.

BAB 16.

129

HOSTING

16.1.5 Kongurasi PHP


Ya, kita atur dulu urusan PHP sebagai bahasa yang umum digunakan oleh
pengembang web. Pasang modul

suphp

agar setiap s ript PHP dijalankan oleh

pemiliknya:

$ sudo apt-get install libapa he2-mod-suphp


Pastikan direktori

/home

sebagai basis suphp, ubah

/et /suphp/suphp. onf,

ganti baris

do root=/var/www:${HOME}/publi _html
menjadi

do root=/home
Non-aktif-kan modul php5 karena sudah diganti dengan modul suphp:

$ sudo a2dismod php5


Kemudian pasang modul untuk PostgreSQL, MySQL, dan grak:

$ sudo apt-get install php5-pgsql php5-mysql php5-gd


Ubahlah

/et /php5/ gi/php.ini

agar pengunjung web nyaman unggah video:

m a x _ e x e u t i o n _t i m e = 1 0 0 0

max_input_time = 1 0 0 0

memory_limit = 1 2 8M

p o s t _ m a x _ s i z e = 1 0 0M

u p l o a d _ m a x _ f i l e s i z e = 1 0 0 0M
Lalu restart web server:

$ sudo servi e apa he2 restart


Kongurasi PHP selesai.

16.1.6 Mail Server


Postx perlu diatur agar boleh menerima relay dari network lain. Misalkan user
mengirim email dari notebook menggunakan Thunderbird. Ubah

master. f,

aktifkan baris

submission

inet

smtps

inet

submission

dan

smtps :

/et /postx/-

n smtpd
smtpd

Karena user a ount menggunakan Linux user, ubahlah /et /default/saslauthd, dari baris:

BAB 16.

130

HOSTING

MECHANISMS="pam"
menjadi

MECHANISMS="shadow"
Restart daemon-nya:

$ sudo servi e saslauthd restart


$ sudo servi e postfix restart

16.1.7 PostgreSQL
Sebaiknya Anda periksa default en oding yang digunakan PostgreSQL.

$ sudo su postgres - "psql - '\l'"


Kalau en oding masih SQL_ASCII berarti Anda harus menggantinya ke UTF8.
Mengapa ?

Karena SQL_ASCII bisa berarti "kalau ada karakter sampah,

biarkan saja". Berikut ini ara mengubahnya:

$ sudo pg_drop luster --stop 8.4 main


$ sudo pg_ reate luster --start -e UTF-8 8.4 main

16.1.8 Kongurasi Awal Virtualmin


Berikutnya kongurasi awal melalui web. Jika Anda memasang desktop, bisa
langsung ke url:
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
Selanjutnya web Virtualmin meminta kita untuk login menggunakan

superuser,

dalam hal ini user saat pemasangan Ubuntu pertama kali.


Pada awal login, Anda dihadapkan pada wizard untuk kongurasi. Se ara
umum Anda ukup memilih

Yes

dan klik

Next

hingga selesai.

Setelah Next

terakhir di-klik, Anda diminta untuk klik:


Re- he k and refresh onguration
Jika lan ar, Anda akan menemui pesan ini:
.. your system is ready for use by Virtualmin.
Jika server berada di belakang rewall, misalnya Anda menggunakan modem
ADSL sebagai gateway, biasanya akan menemui pesan berikut ini:

BAB 16.

131

HOSTING

Default IP address is set to 192.168.1.2, but the dete ted external


address is a tually 180.252.150.215. This is typi ally the result of
being behind a NAT rewall, and should be orre ted on the module
onguration page.
Jika IP publik server adalah statik, maka lanjutkan klik module onguration

System Settings, Virtualmin ConConguration Category, pilih Network settings, lalu:

yang dimaksud. Atau se ara menu melalui

guration.

Pada pilihan

Default IP address for DNS re ords:

ternal address

Automati ally dete t ex-

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 dipastikan 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.

route )

Ini artinya server tidak bisa disentuh (ba a: di-

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!
maka server Anda telah memiliki IP publik.

16.1.9 Mail A ount


Se ara default, Virtualmin menggunakan format

gin.

user.domain untuk IMAP louserdomain, agar sama

Akan lebih nyaman bila formatnya menggunakan

dengan emailnya. Ikuti langkah berikut ini:


1. Masuk ke menu
2. Pada bagian

System Settings, Server Templates, Default Settings.

Edit template se tion, pilihlah Mail for domain.

Format for usernames that in lude domain


namedomain.

3. Pada bagian

pilihlah

user-

4. Klik Save.
Khusus administrator domain bersangkutan, IMAP login tidak memerlukan
domain. Lebih jelasnya Anda bisa lihat di menu Edit Mail and FTP users
kolom IMAP/FTP login, setelah Anda membuat domain nanti.

BAB 16.

132

HOSTING

16.1.10 Hak Akses


virtual server. Ini artinya jika user Anda
reymanx.web.id, maka ia dapat membuat subdomain blog.reymanx.web.id,
download.reymanx.web.id, dst. Atur melalui menu System Settings, A ount
Plans, Default Plan :
Berikanlah user hak untuk membuat

memiliki domain

Unlimited

Limit on number virtual servers:


Klik Save.

16.1.11 Berikan Bash


Bila nanti user login menggunakan ssh (se ure shell), ia akan mendapat shell

/bin/sh. Terus terang, shell ini kurang nyaman, dimana tidak


history dan auto ompletion. Sebaiknya Anda memberikan /bin/bash.
Klik menu System Customization, Custom Shell, Custom shells below. Gantilah
/bin/sh menjadi /bin/bash, lalu klik Save.
Aktifkan auto ompletion di /et /bash.bashr :

sederhana, yaitu
memiliki

1
2

# enable
if

3
4

[
.

bash

ompletion

in

intera tive

/ e t / bash_ ompletion

&& !

shells

shopt

oq

posix ;

then

/ e t / bash_ ompletion

fi
Agar lebih nyaman dalam memasang berbagai aplikasi dari GitHub dan
Bitbu ket, pasanglah aplikasi pengunduhnya:

$ sudo apt-get install git- ore mer urial

16.1.12 Kongurasi Python


Ya, akhirnya kita sampai ke bagian ini, dimana user se ara default menggunakan
Python untuk membuat web. Pasanglah modul WSGI untuk Apa he:

$ sudo apt-get install libapa he2-mod-wsgi


Juga Virtual Environment agar user dimudahkan dalam memasang modul Python
lainnya tanpa perlu memanggil Anda sebagai pengelola hosting.

$ sudo apt-get install python-virtualenv


Driver untuk akses database juga perlu disiapkan:

$ sudo apt-get install python-psy opg2 python-mysqldb


Virtualmin sudah menyediakan apa yang disebut

Server Template.

Saat pendaf-

taran domain, admin diberikan kesempatan memilih bahasa apa yang akan digunakan pelanggannya.

Default-nya adalah PHP, dan alternatif lain adalah

BAB 16.

133

HOSTING

Create Virtual Server, Server onguDefault Settings yang berarti PHP yang
digunakan dengan direktori publi _html sebagai Do umentRoot.

Python.

Pilihan ini terdapat di menu

ration template.

Di sana ada pilihan

Lalu dimana pilihan Python ? Seharusnya ada di bawahnya, namun saat ini
belum ada. Inilah yang akan kita buat sekarang.

Masuklah ke menu System Settings, Server Templates, Create a template


from the default settings. Isilah:

Klik

Python
Sub-servers

Template name:

(bebas)

For use by:

( entang)

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

Dire tives and settings for new websites, dan pada radio button Apa he
dire tives below
baris-baris WSGI berikut ini (paling bawah):

bagian

tambahkan

WSGIS riptAlias / ${HOME}/wsgi/wsgi_handler.py


WSGIDaemonPro ess ${DOM} user=${USER} group=${GROUP} threads=15
WSGIPro essGroup ${DOM}
Klik Save.

16.1.13 Mengubah Sifat Virtualmin


Se ara default Virtualmin menyiapkan direktori

$HOME/publi _html

untuk

sour e PHP, dimana bila URL yang dimaksud dipanggil melalui browser - misalkan http://sabilawebhosting. om - maka sour e PHP yang ada di direktori
itulah yang dijalankan Apa he.
s ript

root do ument. Karena kita juga


root do ument akan diganti dengan

Istilahnya

akan membangun Python hosting, maka

$HOME/wsgi/wsgi_handler.py.

Sebenarnya dengan apa yang Anda sudah pasang tadi sudah ukup bagi
user untuk menyiapkan segala sesuatunya.

Namun sebagai pengelola hosting

yang memahami kebutuhan pelanggan, sebaiknya Anda menyiapkan s ript yang


dimaksud, lengkap dengan

Python virtual environment

pada

home dire tory.

Untunglah Virtualmin memberi kesempatan pada kita untuk menyisipkan


s ript yang dijalankan setelah sebuah domain dibuat. Praktis ini mengurangi
sentuhan manual saat pendaftaran domain.

Masuklah ke menu System Settings, Virtualmin Conguration. Pada Conguration ategory, pilihlah A tions upon server and user reation. Lalu pada
Command to run after making hanges to a server isilah:

/usr/lo al/bin/virtualmin
Klik Save. Selanjutnya buatlah s ript berikut ini.
Listing 16.1: /usr/lo al/bin/virtualmin
1

#! / usr / b i n / python

BAB 16.

2
3
4
5
6
7
8
9

import
import
if

134

HOSTING

os
sys

o s . e n v i r o n [ 'VIRTUALSERVER_ACTION ' ==

o s . system ( ' p

'CREATE_DOMAIN' :

/ u s r / l o a l / e t / v i r t u a l m i n / w s g i %s ' % (

o s . e n v i r o n [ 'VIRTUALSERVER_HOME' ) )
o s . s y s t e m ( ' d %s / w s g i

ln

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 [ '

11

o s . s y s t e m ( ' hown

VIRTUALSERVER_HOME' )

%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' ) )
Pastikan exe utable:

$ sudo hmod 755 /usr/lo al/bin/virtualmin


Lalu siapkan direktori
taruh di

$HOME/ :

/usr/lo al/et /virtualmin/wsgi

yang nantinya akan di-

$ sudo mkdir -p /usr/lo al/et /virtualmin/wsgi


Buatlah monitoring s ript yang berguna untuk

autoreload

daemon Python.

Daemon Python ?
Ya. Setiap s ript Python yang dibuat oleh user akan dijalankan oleh Apa he
sebagai daemon, dalam sebuah sub-pro ess. Monitoring s ript berguna untuk
memantau perubahan le pada direktori $HOME/wsgi. Bila s ript ini mendapati ada le yang berubah, se ara otomatis ia akan mengakhiri dirinya sendiri,
dan pada saat URL situs dipanggil lagi melalui browser, Apa he - se ara otomatis pula - menghidupkan kembali daemon ini.

1
2
3
4
5
6
7
8
9

import
import
import
import
import
import
import

Listing 16.2: /usr/lo al/et /virtualmin/wsgi/monitor.py


os
sys
time
signal
threading
atexit
Queue

_interval = 1.0

5 Interpreter Python mengizinkan kita untuk mengubah le *.py selama s ript sedang berjalan (runtime ). Namun perubahan itu berfungsi saat s ript itu dijalankan ulang.

BAB 16.

135

HOSTING

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

def

17
18
19

_ r e s t a r t ( path ) :
_queue . p u t ( True )
prefix =

print
print

20

' monitor

% ( prefix ,

21

( p i d=%d ) : ' % o s . g e t p i d ( )

>> s y s . s t d e r r ,

'%s

Change

dete ted

'%s

Triggering

to

\ '% s \ ' . '

path )

>> s y s . s t d e r r ,

pro ess

restart . '

% prefix

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

os . k i l l ( os . getpid ( ) ,

def

s i g n a l . SIGINT )

_modified ( path ) :

try

# I f path doesn ' t denote a f i l e and were


previously
# t r a k i n g i t , then i t has been removed or t h e
f i l e type
# has hanged so f o r e a r e s t a r t . I f not
previously
# 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
# 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
# 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 .

if not
return

os . path . i s f i l e ( path ) :
path

in

_times

# Che k f o r when f i l e l a s t m o d i f i e d .

37
38
39
40
41
42
43
44
45
46

mtime = o s . s t a t ( p a t h ) . st_mtime

if

path

not in

_times :

_ t i m e s [ p a t h = mtime

# 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
# 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
# has been r e s t o r e d .

if

mtime

!=

_times [ path :

BAB 16.

47

ex ept

48

50
51
52
53
54
56
57

return

True

# 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
# been removed j u s t b e f o r e s t a t ( ) , so f o r e a
restart .

49

55

136

HOSTING

return
return

True

False

def

_monitor ( ) :

while

1:

# 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 .

58
59

for

60
61

in
if not
ontinue
if not
ontinue
if

module

s y s . modules . v a l u e s ( ) :

h a s a t t r ( module ,

62
63

p a t h = g e t a t t r ( module ,

64

' __file__ ' ) :


' __file__ ' )

path :

65
66

os . path . s p l i t e x t ( path ) [ 1
pyo ' ,

67

path = path [ :

if

68
69
70

' . pyd ' :

in

'.

_modified ( path ) :

return

_ r e s t a r t ( path )

# Che k m o d i f i a t i o n times on f i l e s whi h have


# 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 .

71
72
73

for

74
75

path

if

76
77

in
return

_files :

_modified ( path ) :
_ r e s t a r t ( path )

# 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 .

78
79

try
return
ex ept
pass

80

81
82

_queue . g e t ( t i m e o u t=_ i n t e r v a l )

83
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

def

88

[ ' . py ' ,

_exiting () :

BAB 16.

137

HOSTING

try
ex ept
pass

89

90

_queue . p u t ( True )

91

92
93

_thread . j o i n ( )

94
95

a t e x i t . r e g i s t e r ( _exiting )

96

def

97
98
99
100
101
102

t r a k ( path ) :

if not

path

in

_files :

_ f i l e s . append ( p a t h )

def

103

s t a r t ( i n t e r v a l =1.0) :

global
if

_interval

i n t e r v a l < _interval :

104

_interval = i n t e r v a l

105

global
if not
print

106

_running

107

_lo k . a q u i r e ( )

108

_running :

109

prefix =

110

' monitor

( p i d=%d ) : ' % o s . g e t p i d ( )

>> 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 ( )
Anda bisa salin dari situs aslinya:
http:// ode.google. om/p/modwsgi/wiki/ReloadingSour eCode
Selanjutnya buat

1
2

def

root do ument.
Listing 16.3: wsgi_handler.py

a p p l i a t i o n ( environ ,
status =

' 2 0 0 OK '

output =

' Hello

response_headers =

start_response ) :

World ! '

[ ( ' C o n t e n t t y p e ' ,

' text / plain ' ) ,

( ' C o n t e n t L e n g t h ' ,

s t r ( l e n ( output

)))
6
7
8
9
10
11
12

start_response ( status ,

return
import

os ,

[ output

sys

sys . stdout = sys . stderr

response_headers )

BAB 16.

138

HOSTING

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 (

[:2) )
15

lambda

x:

str (x) ,

sys . version_info

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
17
18
19
20
21
22
23
24

' / 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

s y s . p a t h . append ( env_path )

#os . e n v i r o n [ 'DJANGO_SETTINGS_MODULE ' = ' myproje t .


settings '
#import django . ore . h a n d l e r s . wsgi
#a p p l i a t i o n = django . ore . h a n d l e r s . wsgi . WSGIHandler ( )

import

monitor

monitor . s t a r t ( i n t e r v a l =1.0)
Selesai sudah kongurasi server. Kini saatnya produ tion.

16.1.14 Pendaftaran Domain


Mari dimulai dengan membuat domain perusahaan hosting Anda sendiri, dalam

sabilawebhosting. om.
tual Server. Isilah:

hal ini

Domain name:

Masih di Virtualmin, masuk ke menu

Create Vir-

sabilawebhosting. om

Administration password: ****


Server onguration template: Python
Klik

Create Server.

Sekarang obalah kunjungi:

http://sabilawebhosting. om
Kalau Anda menjumpai:
Hello world!
berarti pendaftaran sudah berlangsung dengan baik. Bila Anda menjumpai:
Server not found
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.

139

HOSTING

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 masingmasing.
Sedangkan untuk mail, mereka bisa mengunjungi subdomain

webmail, dalam

hal ini ontohnya adalah:


http://webmail.sabilawebhosting. om.

16.1.15 User Spa e


User diperkenankan melakukan SSH ke server dengan username awalan nama

reymanx.web.id
reymanx.

domain (default). Jadi jika Anda membuat


se ara otomatis akan membuat user

maka Virtualmin

Katakanlah user reymanx ingin memasang Django , maka setelah ia SSH ke


server, ia bisa gunakan

pip

yang tersedia di

virtual environment 7 :

$ env/bin/pip install django


Setelah selesai mulailah membuat proje t:

$ d wsgi
$ ../env/bin/django-admin.py startproje t myproje t
Lalu ubahlah

1
2

import

$HOME/wsgi/wsgi_handler.py

menjadi seperti ini:

Listing 16.4: wsgi_handler.py untuk Django


os ,

sys

sys . stdout = sys . stderr

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__ )

env_ver =

))
' . ' . j o i n ( map (

[:2) )
6

lambda

x:

str (x) ,

sys . version_info

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
8

' / 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

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.

140

HOSTING

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

import

14
15

monitor

monitor . s t a r t ( i n t e r v a l =1.0)
Kembali ke Firefox url

http://reymanx.web.id,

seharusnya tampil:

It worked!
Beberapa hal lain yang biasa digunakan user adalah:

/site_media/, bisa melalui


Servi es, Congure Website, Aliases and Redire ts. Isilah pada bagian Do ument dire tory aliases. Misalkan From diisi
/site_media/, dan To diisi /home/reymanx/wsgi/myproje t/site_media/.
Untuk pembuatan alias, misalnya untuk path
Virtualmin, yaitu menu

Klik Save. Perubahan baru tersimpan saja, belum dilaksanakan. Untuk


pelaksanaannya klik

Apply Changes

di kanan atas.

Untuk mendaftarkan ron job


ules, S heduled Cron Jobs.

Pendaftaran subdomain melalui menu

(s heduler), masuk ke menu

Webmin Mod-

Create Virtual Server.

Oh iya, sebenarnya juga tersedia Installer Django di sini.

Namun tidak dis-

arankan karena masih menggunakan Fast CGI (konon yang terbaik menggunakan WSGI seperti yang sudah diulas).
Template telah siap. Kini obalah mendaftarkan domain baru pada menu

Create Virtual Server. Setelah memasukkan Domain name


password, pilih Python pada Server onguration template.

dan

Administration
Create Server.

Klik

Kini obalah mengunjungi domain baru tersebut, seharusnya dijumpai pesan:


Hello World!

wsgi/wsgi_handler.py. Jika tadi Anda pilih Default SetServer onguration template, seharusnya Anda menjumpai pesan:

yang berasal dari le

tings

pada

Forbidden
yang artinya Apa he mengharapkan le

16.2

Google Apps

publi _html/index.php.

Bibliogra
[1 http://jabber.rab. o.id/os/web-admin-dengan-virtualmin
[2 http://jabber.rab. o.id/os/pas a-instalasi-linux
[3 http://ja obian.org/writing/pg-en oding-ubuntu
[4 https:// onvore. om/id-python/gathering-online-22-july-2011
[5 http:// ode.google. om/p/modwsgi/wiki/ReloadingSour eCode

141

Indeks
__name__, 35

integer, 11

ALTER TABLE, 50, 51

KDE, 6, 7

Android, 5

konsole, 6

apt-get install, 6
apt-get update, 6

length(), 56

autoin rement eld, 46

Linux, 5
lo ale-gen, 38

BlankOn, 6

lo altime(), 28

break, 14

lower(), 9
lpad(), 56

ontinue, 15
CREATE TABLE, 44

Ma , 5

CREATE VIEW, 52

mktime(), 29

reatedb, 43

modul datetime, 30

reateuser, 42

modul lo ale, 37
modul time, 28

Data Denition Language, 51


Data Manipulation Language, 51

nextval(), 47

date(), 30

None, 39

datestyle, 48

NOT NULL, 44

datetime(), 30
DEFAULT, 44

objek hampa, 39

DELETE FROM, 50

ORDER BY, 48

DROP TABLE, 51

ORDER BY, DESC, 49

dropdb, 43
dropuser, 42

pg_dump, 54
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

int(), 19, 27

sequen e, 46
142

INDEKS

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

143

Anda mungkin juga menyukai