一、fileno簡介
fileno是Python中一個比較基礎的函數,用於返迴文件描述符。文件描述符是在內核中用於標識一個特定的文件的整數值,通常與UNIX系統相關聯。在UNIX系統中,每個進程都有一個文件描述符表,用於管理文件、網絡套接字和其他輸入/輸出資源。使用fileno函數可以獲取文件描述符,進而進行文件讀寫等操作。
二、fileno的用法
在Python中,fileno函數可以應用於三種類型的對象:文件、套接字和管道。下面分別介紹一下三種情況下如何使用fileno函數。
1.文件操作
在文件操作中,我們通常需要先打開一個文件對象,然後才能進行文件讀寫等操作。fileno函數可用於獲取文件對象的文件描述符。其代碼示例如下:
f = open('example.txt', 'r') fd = f.fileno() print(fd)
代碼執行結果將返迴文件對象的文件描述符。
2.網絡套接字
在網絡編程中,我們經常需要使用套接字進行數據傳輸。fileno函數也可用於獲取套接字的文件描述符。其代碼示例如下:
import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(('localhost', 8888)) s.listen(1) fd = s.fileno() print(fd)
代碼執行結果將返回套接字對象的文件描述符。
3.管道
在進程間通信中,我們可以使用管道(pipe)進行數據傳輸。fileno函數也可用於獲取管道的文件描述符。其代碼示例如下:
import os r, w = os.pipe() reader_fd = os.fdopen(r) writer_fd = os.fdopen(w) print(reader_fd.fileno(), writer_fd.fileno())
代碼執行結果將返回管道的兩個文件描述符。
三、fileno函數的進階用法:簡單到匿名
除了上述三種基本情況,fileno函數還有一些進階用法。本部分將介紹fileno的另外三種情況:匿名管道、匿名和非阻塞I/O。
1.匿名管道
在UNIX系統中,管道(pipe)是一種可用於協調進程間通信的IPC機制。UNIX管道分為有名管道和匿名管道,其中匿名管道不指向文件系統中的任何文件,而是只在進程間傳遞數據。在Python中,我們可以使用os模塊中的pipe函數創建一個匿名管道,並使用fileno函數獲取其文件描述符,實現進程間通信。其代碼示例如下:
import os r, w = os.pipe() pid = os.fork() if pid: os.close(w) r = os.fdopen(r) print('Parent got:', r.readline()) else: os.close(r) w = os.fdopen(w, 'w') print('child sending') w.write('hello parent\n') w.close()
代碼執行結果將在父進程打印”Parent got: hello parent”,在子進程打印”child sending”。
2.匿名
我們可以利用fileno函數以及ctypes模塊中的memmove函數,來實現Python中的匿名內存映射。其代碼示例如下:
import mmap import ctypes import os m = mmap.mmap(-1,4096, mmap.MAP_ANONYMOUS | mmap.MAP_PRIVATE) m.write(b'hello') os.dup2(ctypes.c_int(m.fileno()).value,0) os.system('cat')
代碼執行結果將在命令行打印”hello”。
3.非阻塞I/O
在進行I/O操作時,如果程序一直等待I/O操作完成之後才能繼續執行,就會產生阻塞。為了避免阻塞,並且不影響程序的執行,可以使用非阻塞的I/O。Python的select函數是用於多路復用的一個函數,我們可以使用fileno函數將文件描述符與select函數結合起來,實現非阻塞的I/O操作。其代碼示例如下:
import select import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(('localhost', 8888)) s.listen(1) fd = s.fileno() rlist = [s] wlist = [] while True: readable, writable, exceptional = select.select(rlist, wlist, rlist) for s in readable: if s is r: conn, addr = s.accept() rlist.append(conn) else: data = s.recv(1024) if data == b'': rlist.remove(s) else: wlist.append(s) for s in writable: s.send(b'hello') wlist.remove(s)
代碼執行結果將在控制台輸出”hello”。
原創文章,作者:BICZ,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/138128.html