久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

淺析Python中的struct模塊

 看風景D人 2014-01-07

    最近在學習python網絡編程這一塊,,在寫簡單的socket通信代碼時,,遇到了struct這個模塊的使用,當時不太清楚這到底有和作用,,后來查閱了相關資料大概了解了,,在這里做一下簡單的總結。

    了解c語言的人,,一定會知道struct結構體在c語言中的作用,,它定義了一種結構,里面包含不同類型的數據(int,char,bool等等),,方便對某一結構對象進行處理,。而在網絡通信當中,,大多傳遞的數據是以二進制流(binary data)存在的。當傳遞字符串時,,不必擔心太多的問題,,而當傳遞諸如int、char之類的基本數據的時候,,就需要有一種機制將某些特定的結構體類型打包成二進制流的字符串然后再網絡傳輸,,而接收端也應該可以通過某種機制進行解包還原出原始的結構體數據。python中的struct模塊就提供了這樣的機制,,該模塊的主要作用就是對python基本類型值與用python字符串格式表示的C struct類型間的轉化(This module performs conversions between Python values and C structs represented as Python strings.),。stuct模塊提供了很簡單的幾個函數,下面寫幾個例子,。

1,、基本的pack和unpack

    struct提供用format specifier方式對數據進行打包和解包(Packing and Unpacking)。例如:

1
2
3
4
5
6
7
8
9
10
11
12
import struct
import binascii
values = (1, 'abc', 2.7)
s = struct.Struct('I3sf')
packed_data = s.pack(*values)
unpacked_data = s.unpack(packed_data)
  
print 'Original values:', values
print 'Format string :', s.format
print 'Uses :', s.size, 'bytes'
print 'Packed Value :', binascii.hexlify(packed_data)
print 'Unpacked Type :', type(unpacked_data), ' Value:', unpacked_data

輸出:

Original values: (1, 'abc', 2.7)
Format string : I3sf
Uses : 12 bytes
Packed Value : 0100000061626300cdcc2c40
Unpacked Type : <type 'tuple'>  Value: (1, 'abc', 2.700000047683716)

代碼中,,首先定義了一個元組數據,,包含int、string,、float三種數據類型,,然后定義了struct對象,并制定了format‘I3sf’,,I 表示int,,3s表示三個字符長度的字符串,f 表示 float,。最后通過struct的pack和unpack進行打包和解包,。通過輸出結果可以發(fā)現,value被pack之后,,轉化為了一段二進制字節(jié)串,,而unpack可以把該字節(jié)串再轉換回一個元組,但是值得注意的是對于float的精度發(fā)生了改變,,這是由一些比如操作系統等客觀因素所決定的,。打包之后的數據所占用的字節(jié)數與C語言中的struct十分相似。定義format可以參照官方api提供的對照表:

image

2,、字節(jié)順序

   另一方面,,打包的后的字節(jié)順序默認上是由操作系統的決定的,當然struct模塊也提供了自定義字節(jié)順序的功能,,可以指定大端存儲,、小端存儲等特定的字節(jié)順序,對于底層通信的字節(jié)順序是十分重要的,不同的字節(jié)順序和存儲方式也會導致字節(jié)大小的不同,。在format字符串前面加上特定的符號即可以表示不同的字節(jié)順序存儲方式,,例如采用小端存儲 s = struct.Struct(‘<I3sf’)就可以了。官方api library 也提供了相應的對照列表:

image

3,、利用buffer,,使用pack_into和unpack_from方法

  使用二進制打包數據的場景大部分都是對性能要求比較高的使用環(huán)境。而在上面提到的pack方法都是對輸入數據進行操作后重新創(chuàng)建了一個內存空間用于返回,,也就是說我們每次pack都會在內存中分配出相應的內存資源,這有時是一種很大的性能浪費,。struct模塊還提供了pack_into() 和 unpack_from()的方法用來解決這樣的問題,,也就是對一個已經提前分配好的buffer進行字節(jié)的填充,而不會每次都產生一個新對象對字節(jié)進行存儲,。

1
2
3
4
5
6
7
8
9
10
11
12
import struct
import binascii
import ctypes
  
values = (1, 'abc', 2.7)
s = struct.Struct('I3sf')
prebuffer = ctypes.create_string_buffer(s.size)
print 'Before :',binascii.hexlify(prebuffer)
s.pack_into(prebuffer,0,*values)
print 'After pack:',binascii.hexlify(prebuffer)
unpacked = s.unpack_from(prebuffer,0)
print 'After unpack:',unpacked

輸出:

Before : 000000000000000000000000
After pack: 0100000061626300cdcc2c40
After unpack: (1, 'abc', 2.700000047683716)
對比使用pack方法打包,,pack_into 方法一直是在對prebuffer對象進行操作,沒有產生多余的內存浪費,。另外需要注意的一點是,,pack_into和unpack_from方法均是對string buffer對象進行操作,并提供了offset參數,,用戶可以通過指定相應的offset,,使相應的處理變得更加靈活。例如,,我們可以把多個對象pack到一個buffer里面,,然后通過指定不同的offset進行unpack:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import struct
import binascii
import ctypes
  
values1 = (1, 'abc', 2.7)
values2 = ('defg',101)
s1 = struct.Struct('I3sf')
s2 = struct.Struct('4sI')
  
prebuffer = ctypes.create_string_buffer(s1.size+s2.size)
print 'Before :',binascii.hexlify(prebuffer)
s1.pack_into(prebuffer,0,*values1)
s2.pack_into(prebuffer,s1.size,*values2)
print 'After pack:',binascii.hexlify(prebuffer)
print s1.unpack_from(prebuffer,0)
print s2.unpack_from(prebuffer,s1.size)

輸出:

Before : 0000000000000000000000000000000000000000
After pack: 0100000061626300cdcc2c406465666765000000
(1, 'abc', 2.700000047683716)
('defg', 101)

    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內容中的聯系方式、誘導購買等信息,,謹防詐騙,。如發(fā)現有害或侵權內容,請點擊一鍵舉報,。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多