将代码作为模块导入比 Python 中的单个代码块运行速度慢得多
Importing code as a module runs much slower than a single block of code in Python
我正在编写代码以将图像从 raspberry-pi3 流式传输到我的笔记本电脑。
我写了两个版本的代码,一个使用模块,另一个作为单个代码块。
我把代码放在这里(代码后面有更多细节)
运行速度快的代码:
import picamera
import socket
import struct
import time
import io
stream_client= socket.socket(socket.AF_INET,socket.SOCK_STREAM)
stream_client.connect(('192.168.43.34',9000))
print('connected')
camera = picamera.PiCamera()
camera.resolution=(320,240)
camera.color_effects=(128,128)
camera.framerate=18
time.sleep(2)
stream = io.BytesIO()
count=0
start=time.time()
try:
for i in camera.capture_continuous(stream,'jpeg',use_video_port=True):
count+=1
stream_client.sendall(struct.pack('<L',stream.tell()))
stream_client.sendall(struct.pack('<h',count))
stream_client.sendall(stream.getvalue())
stream.seek(0)
stream.truncate()
if(time.time()-start>10):
break
finally:
stream_client.sendall(struct.pack('<L',0))
stream_client.close()
camera.close()
print('connection closed')
运行慢的代码:
模块(包含在同一文件夹中的不同文件 "CameraStreamModule.py" 中):
'''
MODULE NAME: CAMERA STREAMING MODULE
OBJECTIVE: TO SEND IMAGE DATA FROM RASPBERRY-PI3 TO LAPTOP VIA TCP/IP STREAM
HARDWARE USED: RASPBERRY PI 3, PI CAMERA REV 1.3
PYTHON VERSION: 3.5.3
DATE WRITTEN: 8-1-2018
'''
'''************************************************************** IMPORTING MODULES ***********************************************************************'''
import picamera # PI CAMERA MODULE
import socket # MODULE TO HANDLE TCP/IP CONNECTION AND TRANSFER
import struct # MODULE TO CONVERT DATA TO BYTE-LIKE OBJECTS (REQUIRED BY SOCKET METHODS)
import time # MODULE FOR TIME RELATED FUNCTIONS
import io # MODULE USED TO CREATE IN-MEMORY DATA STREAMS
'''************************************************************ MODULE IMPORTS END HERE *******************************************************************'''
'''*********************************************************** DECLARING GLOBAL VARIABLES *****************************************************************'''
LIMITED_STREAM = False # Stream only for short time when true
LIMIT_TIME= 10 # Seconds
stream = io.BytesIO()
stream_client= socket.socket(socket.AF_INET,socket.SOCK_STREAM)
camera = picamera.PiCamera()
count=0
'''*********************************************************** GLOBAL VARIABLES END HERE ******************************************************************'''
'''************************************************************** METHOD DEFINITIONS ***********************************************************************'''
def Client_init (Server_ip,Server_port): # (str,int) expected as parameter
global stream_client,start,LIMITED_STREAM
stream_client.connect((Server_ip,Server_port))
if LIMITED_STREAM :
start=time.time()
print('connected')
def Camera_init (Resolution_tuple,Colour_tuple,Frame_rate): # (int_tuple,int_tuple,int) expected as parameter
global camera
camera.resolution= Resolution_tuple
camera.color_effects=Colour_tuple
camera.framerate= Frame_rate
time.sleep(2)
'''
THIS METHOD IS INTENDED TO BE CALLED INSIDE "for i in camera.capture_continuous(stream,'jpeg',use_video_port=True):" CONTINUOUSLY. ALSO .close() FOR SOCKET
AND CAMERA MUST BE CALLED SEPERATELY.
'''
def Send_frame ():
global count,stream_client,stream,LIMITED_STREAM
count+=1
stream_client.sendall(struct.pack('<L',stream.tell()))
stream_client.sendall(struct.pack('<h',count))
stream_client.sendall(stream.getvalue())
stream.seek(0)
stream.truncate()
if LIMITED_STREAM:
if(time.time()-start>LIMIT_TIME):
raise Exception('Time Finished')
'''********************************************************* METHOD DEFINITIONS END HERE ******************************************************************'''
调用代码:
import importlib
Camera_module= importlib.import_module('CameraStreamModule')
Camera_module.LIMITED_STREAM= True
Camera_module.Client_init('192.168.1.102',9000)
Camera_module.Camera_init((320,240),(128,128),18)
try:
for i in Camera_module.camera.capture_continuous(Camera_module.stream,'jpeg',use_video_port=True):
Camera_module.Send_frame()
finally:
Camera_module.camera.close()
Camera_module.stream_client.sendall(struct.pack('<L',0))
Camera_module.stream_client.close()
print('connection closed')
第一个代码在 10 秒内传输了大约 179 张图像,第二个版本处理了大约 133 张图像,这大大减少了。我只是想创建一个模块来使代码更易于管理和阅读。
我最近才开始在 Python 中编码,我知道我的编码方法对于更有经验的编码人员来说可能看起来很荒谬(相信我,我正在努力改进)。谁能告诉我这种放缓的原因是什么?
我观察到即使更改 WiFi 连接也会对给定时间内传输的数据量产生影响,因此我将两个版本的代码的 WiFi 连接保持相同。
我认为这种减速的发生是因为我在模块之间来回传递大量数据?
无论如何,欢迎任何关于代码的advice/help。
P.S:如果您觉得我在这个平台上的提问方式不够到位,需要补充或减少细节,请告诉我。
好的,我发现问题了。实际上,在我创建的接收者代码中,我写了很多用于调试的 print() 语句。这导致了延迟,因此我丢失了一些数据,因为套接字传输是异步的(而且我没有处理代码中的数据丢失问题)。随之而来的还有可能是在模块之间来回传递大数组数据的延迟导致了这个问题
留下这个答案以防有人觉得它有用。
我正在编写代码以将图像从 raspberry-pi3 流式传输到我的笔记本电脑。 我写了两个版本的代码,一个使用模块,另一个作为单个代码块。 我把代码放在这里(代码后面有更多细节)
运行速度快的代码:
import picamera
import socket
import struct
import time
import io
stream_client= socket.socket(socket.AF_INET,socket.SOCK_STREAM)
stream_client.connect(('192.168.43.34',9000))
print('connected')
camera = picamera.PiCamera()
camera.resolution=(320,240)
camera.color_effects=(128,128)
camera.framerate=18
time.sleep(2)
stream = io.BytesIO()
count=0
start=time.time()
try:
for i in camera.capture_continuous(stream,'jpeg',use_video_port=True):
count+=1
stream_client.sendall(struct.pack('<L',stream.tell()))
stream_client.sendall(struct.pack('<h',count))
stream_client.sendall(stream.getvalue())
stream.seek(0)
stream.truncate()
if(time.time()-start>10):
break
finally:
stream_client.sendall(struct.pack('<L',0))
stream_client.close()
camera.close()
print('connection closed')
运行慢的代码:
模块(包含在同一文件夹中的不同文件 "CameraStreamModule.py" 中):
'''
MODULE NAME: CAMERA STREAMING MODULE
OBJECTIVE: TO SEND IMAGE DATA FROM RASPBERRY-PI3 TO LAPTOP VIA TCP/IP STREAM
HARDWARE USED: RASPBERRY PI 3, PI CAMERA REV 1.3
PYTHON VERSION: 3.5.3
DATE WRITTEN: 8-1-2018
'''
'''************************************************************** IMPORTING MODULES ***********************************************************************'''
import picamera # PI CAMERA MODULE
import socket # MODULE TO HANDLE TCP/IP CONNECTION AND TRANSFER
import struct # MODULE TO CONVERT DATA TO BYTE-LIKE OBJECTS (REQUIRED BY SOCKET METHODS)
import time # MODULE FOR TIME RELATED FUNCTIONS
import io # MODULE USED TO CREATE IN-MEMORY DATA STREAMS
'''************************************************************ MODULE IMPORTS END HERE *******************************************************************'''
'''*********************************************************** DECLARING GLOBAL VARIABLES *****************************************************************'''
LIMITED_STREAM = False # Stream only for short time when true
LIMIT_TIME= 10 # Seconds
stream = io.BytesIO()
stream_client= socket.socket(socket.AF_INET,socket.SOCK_STREAM)
camera = picamera.PiCamera()
count=0
'''*********************************************************** GLOBAL VARIABLES END HERE ******************************************************************'''
'''************************************************************** METHOD DEFINITIONS ***********************************************************************'''
def Client_init (Server_ip,Server_port): # (str,int) expected as parameter
global stream_client,start,LIMITED_STREAM
stream_client.connect((Server_ip,Server_port))
if LIMITED_STREAM :
start=time.time()
print('connected')
def Camera_init (Resolution_tuple,Colour_tuple,Frame_rate): # (int_tuple,int_tuple,int) expected as parameter
global camera
camera.resolution= Resolution_tuple
camera.color_effects=Colour_tuple
camera.framerate= Frame_rate
time.sleep(2)
'''
THIS METHOD IS INTENDED TO BE CALLED INSIDE "for i in camera.capture_continuous(stream,'jpeg',use_video_port=True):" CONTINUOUSLY. ALSO .close() FOR SOCKET
AND CAMERA MUST BE CALLED SEPERATELY.
'''
def Send_frame ():
global count,stream_client,stream,LIMITED_STREAM
count+=1
stream_client.sendall(struct.pack('<L',stream.tell()))
stream_client.sendall(struct.pack('<h',count))
stream_client.sendall(stream.getvalue())
stream.seek(0)
stream.truncate()
if LIMITED_STREAM:
if(time.time()-start>LIMIT_TIME):
raise Exception('Time Finished')
'''********************************************************* METHOD DEFINITIONS END HERE ******************************************************************'''
调用代码:
import importlib
Camera_module= importlib.import_module('CameraStreamModule')
Camera_module.LIMITED_STREAM= True
Camera_module.Client_init('192.168.1.102',9000)
Camera_module.Camera_init((320,240),(128,128),18)
try:
for i in Camera_module.camera.capture_continuous(Camera_module.stream,'jpeg',use_video_port=True):
Camera_module.Send_frame()
finally:
Camera_module.camera.close()
Camera_module.stream_client.sendall(struct.pack('<L',0))
Camera_module.stream_client.close()
print('connection closed')
第一个代码在 10 秒内传输了大约 179 张图像,第二个版本处理了大约 133 张图像,这大大减少了。我只是想创建一个模块来使代码更易于管理和阅读。
我最近才开始在 Python 中编码,我知道我的编码方法对于更有经验的编码人员来说可能看起来很荒谬(相信我,我正在努力改进)。谁能告诉我这种放缓的原因是什么?
我观察到即使更改 WiFi 连接也会对给定时间内传输的数据量产生影响,因此我将两个版本的代码的 WiFi 连接保持相同。
我认为这种减速的发生是因为我在模块之间来回传递大量数据?
无论如何,欢迎任何关于代码的advice/help。
P.S:如果您觉得我在这个平台上的提问方式不够到位,需要补充或减少细节,请告诉我。
好的,我发现问题了。实际上,在我创建的接收者代码中,我写了很多用于调试的 print() 语句。这导致了延迟,因此我丢失了一些数据,因为套接字传输是异步的(而且我没有处理代码中的数据丢失问题)。随之而来的还有可能是在模块之间来回传递大数组数据的延迟导致了这个问题
留下这个答案以防有人觉得它有用。