7. การนำเข้าและส่งออกข้อมูล (Input and Output)

7.1 การจัดรูปแบบเอาต์พุต (Fancier Output Formatting)
7.2 การอ่านเขียนไฟล์ (Reading and Writing Files)



7.1 การจัดรูปแบบเอาต์พุต (Fancier Output Formatting)

สามารถจัดรูปแบบได้สองแบบหลัก คือใช้ฟังก์ชั่น และใช้ตัวกระทำ %

ตัวอย่างการใช้ฟังก์ชั่นแปลงเป็นตัวอักขระ str() ซึ่งให้คนอ่านง่าย หรือแปลงแบบดิบ repr() คือให้ระบบอ่านง่าย (สามารถเขียนอีกแบบภายใต้เครื่องหมาย ``)

>>> s = 'Hello, world.'
>>> str(s)
'Hello, world.'

>>> repr(s)
"'Hello, world.'"

>>> str(0.1)
'0.1'

>>> repr(0.1)
'0.10000000000000001'

>>> x = 10 * 3.25
>>> y = 200 * 200
>>> s = 'The value of x is ' + repr(x) + ', and y is ' + repr(y) + '...'
>>> print s
The value of x is 32.5, and y is 40000...

>>> # The repr() of a string adds string quotes and backslashes:
... hello = 'hello, world\n'
>>> hellos = repr(hello)
>>> print hellos
'hello, world\n'

>>> # The argument to repr() may be any Python object:
... repr((x, y, ('spam', 'eggs')))
"(32.5, 40000, ('spam', 'eggs'))"

>>> # reverse quotes are convenient in interactive sessions:
... `x, y, ('spam', 'eggs')`
"(32.5, 40000, ('spam', 'eggs'))"

ตัวอย่างการใช้ฟังก์ชั่น repr() ร่วมกับเมธอดจัดชิดขวาของสตริง rjust() เทียบกับการใช้ตัวกระทำจัดรูปแบบ %

>>> for x in range(1, 11):
...     print repr(x).rjust(2), repr(x*x).rjust(3),
...     # Note trailing comma on previous line
...     print repr(x*x*x).rjust(4)
...
 1   1    1
 2   4    8
 3   9   27
 4  16   64
 5  25  125
 6  36  216
 7  49  343
 8  64  512
 9  81  729
10 100 1000

>>> for x in range(1,11):
...     print '%2d %3d %4d' % (x, x*x, x*x*x)
... 
 1   1    1
 2   4    8
 3   9   27
 4  16   64
 5  25  125
 6  36  216
 7  49  343
 8  64  512
 9  81  729
10 100 1000

ลองดูเมธอด zfill() บ้าง

>>> '12'.zfill(5)
'00012'

>>> '-3.14'.zfill(7)
'-003.14'

>>> '3.14159265359'.zfill(5)
'3.14159265359'

เทียบกับการใช้ %

>>> import math
>>> print 'The value of PI is approximately %5.3f.' % math.pi
The value of PI is approximately 3.142.

อีกอันนึงเป็นการจัดชิดขอบซ้ายขวาด้วย %

>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678}
>>> for name, phone in table.items():
...     print '%-10s ==> %10d' % (name, phone)
... 
Jack       ==>       4098
Dcab       ==>       7678
Sjoerd     ==>       4127

พิเศษนิดนึงสำหรับตัวจัดรูปสตริง %s คือถ้าข้อมูลไม่อยู่ในรูปสตริง เขาจะแปลงอัตโนมัติด้วยฟังก์ชั่น str()

>>> print "%s %s %s" % (1, True, None)
1 True None

พิเศษกว่านั้น ถ้าข้อมูลเป็นดิกชันนารี ยังใช้รูปแบบ %(name)format ได้อีกด้วย

>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
>>> print 'Jack: %(Jack)d; Sjoerd: %(Sjoerd)d; Dcab: %(Dcab)d' % table
Jack: 4098; Sjoerd: 4127; Dcab: 8637678


7.2 การอ่านเขียนไฟล์ (Reading and Writing Files)

เปิดไฟล์ด้วยฟังก์ชั่น open(filename, mode) ได้ค่าเป็น ไฟล์ออปเจกต์

>>> f=open('/tmp/workfile', 'w')
>>> print f
<open file '/tmp/workfile', mode 'w' at 80a0960>

mode เป็นได้ดังนี้

  • 'r' อ่านอย่างเดียว ตัวนี้เป็นค่าปริยาย
  • 'w' เขียนอย่างเดียว ถ้ามีเนื้อเก่าจะถูกทับหมด
  • 'a' เติมอย่างเดียว คือเขียนต่อที่ท้ายไฟล์
  • 'r+' ทั้งอ่านและเขียน (ใช้ร่วมกับเมธอด seek() ในการเลื่อนตำแหน่งอ่านเขียน)

สำหรับเครื่องวินโดวส์และแมคอินทอช จะมีการเปิดแบบไบนารีด้วย ดังนั้นจะมีโหมดเพิ่มคือ 'rb' 'wb' และ 'r+b'
การจัดการไฟล์ระหว่างการเปิดแบบอักขระกับการเปิดแบบไบนารีคือ ในการเปิดแบบอักขระ ระบบจะเติมการจบบรรทัดด้วยอักขระพิเศษเพิ่มเข้าไป ทำให้เกิดปัญหาถ้าไฟล์นั้นเป็นไบนารีไฟล์

7.2.1 เมธอดที่ใช้ (Methods of File Objects)
f.read([ size ])
ถ้าไม่ระบุขนาดไบต์หรือขนาดเป็นลบ เขาจะอ่านทั้งไฟล์ ถ้าอ่านไฟล์จนหมดแล้ว จะคืนค่าเป็นอักขระว่าง ("")

>>> f.read()
'This is the entire file.\n'

>>> f.read()
''
f.readline()
อ่านหนึ่งบรรทัด คืออ่านจนพบอักขระ \n ถ้าอ่านไฟล์จนหมดแล้ว จะคืนค่าเป็นอักขระว่าง ("")

>>> f.readline()
'This is the first line of the file.\n'

>>> f.readline()
'Second line of the file\n'

>>> f.readline()
''
f.readlines()
อ่านทั้งไฟล์โดยแยกแต่ละบรรทัดเป็นแต่ละสมาชิกในลิสต์

>>> f.readlines()
['This is the first line of the file.\n', 'Second line of the file\n']
for line in f:
อันนี้ไม่ใช่เมธอด แต่เป็นประโยคการเขียนแบบพิเศษ ที่ใช้เป็นปกติในไพธอน อ่านโค๊ดง่าย และเหมาะสมในการใช้งานจริง

>>> for line in f:
        print line,
This is the first line of the file.
Second line of the file
f.write(string)
เขียนสตริงก์ลงไฟล์ คืนค่าเป็น None

>>> f.write('This is a test\n')

ถ้าข้อมูลไม่ได้อยู่ในรูปสตริง ต้องแปลงก่อน

>>> value = ('the answer', 42)
>>> s = str(value)
>>> f.write(s)
f.tell()
ใช้บอกตำแหน่งปัจจุบันของไฟล์ นับจากต้นไฟล์
f.seek(offset [, from_what])
ใช้ตั้งตำแหน่งที่จะอ่านเขียนไฟล์ offset คือจำนวนไบต์ from_what คือตำแหน่งอ้างอิง

  • 0 หรือ ไม่ใส่ คือเทียบจากต้นไฟล์
  • 1 คือ จากตำแหน่งปัจจุบัน
  • 2 คือ จากท้ายไฟล์
>>> f = open('/tmp/workfile', 'r+')
>>> f.write('0123456789abcdef')
>>> f.seek(5)     # Go to the 6th byte in the file
>>> f.read(1)        
'5'

>>> f.seek(-3, 2) # Go to the 3rd byte before the end
>>> f.read(1)
'd'
f.close()
ปิดการทำงานกับไฟล์นั้น ถ้าปิดแล้วกลับมาอ่านอีกจะเกิดข้อผิดพลาด

>>> f.close()
>>> f.read()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ValueError: I/O operation on closed file
7.2.2 ปิคเกิล (The pickle Module)

เป็นการเก็บออปเจคต์ลงไฟล์แบบไร้ข้อจำกัด ดูเรื่องปิกเกิลในบรรณสารของไพธอน
ขั้นตอนการทำงานคือ ไพธอนจะแปลงออปเจคต์เป็นสตริงก่อน เรียกว่าปิกกลิง (pickling) เวลานำกลับจะแปลงสคริงนั้นกลับเป็นออปเจคต์อีกที เรียกว่า อันปิกกลิง (unpickling)

ตัวอย่างการใช้งาน สมมุติว่ามีออปเจคต์ x ที่เราต้องการเก็บ ลงไว้ในไฟล์ที่เปิดไว้แล้ว คือไฟล์ออปเจคต์ f รูปแบบคือ

pickle.dump(x, f)

เวลานำกลับก็ใช้ว่า (f ต้องถูกเปิดอยู่ก่อนแล้ว)

x = pickle.load(f)