目录
一、os 库
1.os.system函数
os.system方法是os模块最基础的方法,其它的方法一般在该方法基础上封装完成。
system函数可以将字符串转化成命令在服务器上运行;其原理是每一条system函数执行时,其会创建一个子进程在系统上执行命令行,子进程的执行结果无法影响主进程;
- 上述原理会导致当需要执行多条命令行的时候可能得不到预期的结果;
#! /usr/bin/python
# -*- coding: utf-8 -*-
import os
os.system("cd ~/Desktop/Test/test/ && touch test.txt")
# && 可以用 ; 替换
2.其他
- os.sep可以取代操作系统特定的路径分隔符。windows下为 “\\”
- os.name字符串指示你正在使用的平台。比如对于Windows,它是'nt',而对于Linux/Unix用户,它是'posix'。
- os.getcwd()函数得到当前工作目录,即当前Python脚本工作的目录路径。
- os.getenv()获取一个环境变量,如果没有返回none
- os.putenv(key, value)设置一个环境变量值
- os.listdir(path)返回指定目录下的所有文件和目录名。
- os.remove(path)函数用来删除一个文件。
- os.system(command)函数用来运行shell命令。
- os.linesep字符串给出当前平台使用的行终止符。例如,Windows使用'\r\n',Linux使用'\n'而Mac使用'\r'。
- os.curdir:返回当前目录('.')
- os.chdir(dirname):改变工作目录到dirname 相当于shell下cd
- os.makedirs('dirname1/dirname2') 可生成多层递归目录
- os.removedirs('dirname1') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
- os.mkdir('dirname') 生成单级目录;相当于shell中mkdir dirname
- os.rmdir('dirname') 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
- os.rename("oldname","newname") 重命名文件/目录
- os.path常用方法:
- os.path.isfile()和os.path.isdir()函数分别检验给出的路径是一个文件还是目录。
- os.path.exists()函数用来检验给出的路径是否真地存在
- os.path.getsize(name):获得文件大小,如果name是目录返回0L
- os.path.abspath(name):获得绝对路径
- os.path.normpath(path):规范path字符串形式
- os.path.split(path) :将path分割成目录和文件名二元组返回。
- os.path.splitext():分离文件名与扩展名
- os.path.join(path,name):连接目录与文件名或目录;使用“\”连接
- os.path.basename(path):返回文件名
- os.path.dirname(path):返回文件路径
3. 获取上一级目录的方式
import os
print '***获取当前目录***'
print os.getcwd()
print os.path.abspath(os.path.dirname(__file__))
print '***获取上级目录***'
print os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
print os.path.abspath(os.path.dirname(os.getcwd()))
print os.path.abspath(os.path.join(os.getcwd(), ".."))
print '***获取上上级目录***'
print os.path.abspath(os.path.join(os.getcwd(), "../.."))
二、thread 线程
如果主线程准备退出的时候,不需要等待某些子线程完成,就可以为这些子线程设置守护线程标记。该标记值为真的时候,标示线程是不重要的,或者说该线程只是用来等待客户端请求而不做其他任何事情。
使用下面的语句:thread.daemon=True 可以将一个线程设置为守护线程。同样的也可以通过这个值来查看线程的守护状态。一个新的子线程会继承父线程的守护标记。整个python程序(也可以称作主线程)将在所有的非守护线程退出之后才退出。
Python中使用线程有两种方式:函数或者用类来包装线程对象。
1. start_new_thread
函数式:调用thread模块中的start_new_thread()函数来产生新线程。语法如下:
thread.start_new_thread ( function, args[, kwargs] )
参数说明:
- function - 线程函数。
- args - 传递给线程函数的参数,他必须是个tuple类型。
- kwargs - 可选参数。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import thread
import time
# 为线程定义一个函数
def print_time( threadName, delay):
count = 0
while count < 5:
time.sleep(delay)
count += 1
print "%s: %s" % ( threadName, time.ctime(time.time()) )
# 创建两个线程
try:
thread.start_new_thread( print_time, ("Thread-1", 2, ) )
thread.start_new_thread( print_time, ("Thread-2", 4, ) )
except:
print "Error: unable to start thread"
while 1:
pass
2. Threading
Python通过两个标准库thread和threading提供对线程的支持。thread提供了低级别的、原始的线程以及一个简单的锁。
threading 模块提供的其他方法:
- threading.currentThread(): 返回当前的线程变量。
- threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
- threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
除了使用方法外,线程模块同样提供了Thread类来处理线程,Thread类提供了以下方法:
- run(): 用以表示线程活动的方法。
- start():启动线程活动。
- join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。
- isAlive(): 返回线程是否活动的。
- getName(): 返回线程名。
- setName(): 设置线程名。
使用Threading模块创建线程,直接从threading.Thread继承,然后重写__init__方法和run方法:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import threading
import time
exitFlag = 0
class myThread (threading.Thread): #继承父类threading.Thread
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self): #把要执行的代码写到run函数里面 线程在创建后会直接运行run函数
print "Starting " + self.name
print_time(self.name, self.counter, 5)
print "Exiting " + self.name
def print_time(threadName, delay, counter):
while counter:
if exitFlag:
(threading.Thread).exit()
time.sleep(delay)
print "%s: %s" % (threadName, time.ctime(time.time()))
counter -= 1
# 创建新线程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)
# 开启线程
thread1.start()
thread2.start()
print "Exiting Main Thread"
3.关闭线程
单线程销毁
def _async_raise(tid, exctype):
tid = ctypes.c_long(tid)
if not inspect.isclass(exctype):
exctype = type(exctype)
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
if res == 0:
raise ValueError("invalid thread id")
elif res != 1:
ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
raise SystemError("PyThreadState_SetAsyncExc failed")
def stop_thread(thread):
_async_raise(thread.ident, SystemExit)
多线程销毁
import threading,time,random
class Messy:
def __init__(self):
self.__messy = 0
def m(self,i):
# 随机时间进行打印
time.sleep(random.random()*2)
print(i)
if i == 1:
self.__messy = 1
def main(self):
Threads = []
# 将会启动10个线程,线程id为 1 时全部线程终止!
for i in range(10):
t = threading.Thread(target=self.m,args=(i,))
t.daemon = 1
Threads.append(t)
# 启动所有线程
for i in Threads:
i.start()
# 当标志位【 messy 】时所有多线程结束
while 1:
if self.__messy:
break
print('线程已退出!')
Messy().main()
# 继续执行后续程序
for i in range(5):
print('yeah!')
4.线程同步
- 如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步。
- 使用Thread对象的Lock和Rlock可以实现简单的线程同步,这两个对象都有acquire方法和release方法,对于那些需要每次只允许一个线程操作的数据,可以将其操作放到acquire和release方法之间。如下:
- 多线程的优势在于可以同时运行多个任务(至少感觉起来是这样)。但是当线程需要共享数据时,可能存在数据不同步的问题。
- 考虑这样一种情况:一个列表里所有元素都是0,线程"set"从后向前把所有元素改成1,而线程"print"负责从前往后读取列表并打印。
- 那么,可能线程"set"开始改的时候,线程"print"便来打印列表了,输出就成了一半0一半1,这就是数据的不同步。为了避免这种情况,引入了锁的概念。
- 锁有两种状态——锁定和未锁定。每当一个线程比如"set"要访问共享数据时,必须先获得锁定;如果已经有别的线程比如"print"获得锁定了,那么就让线程"set"暂停,也就是同步阻塞;等到线程"print"访问完毕,释放锁以后,再让线程"set"继续。
- 经过这样的处理,打印列表时要么全部输出0,要么全部输出1,不会再出现一半0一半1的尴尬场面。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import threading
import time
class myThread (threading.Thread):
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self):
print "Starting " + self.name
# 获得锁,成功获得锁定后返回True
# 可选的timeout参数不填时将一直阻塞直到获得锁定
# 否则超时后将返回False
threadLock.acquire()
print_time(self.name, self.counter, 3)
# 释放锁
threadLock.release()
def print_time(threadName, delay, counter):
while counter:
time.sleep(delay)
print "%s: %s" % (threadName, time.ctime(time.time()))
counter -= 1
threadLock = threading.Lock()
threads = []
# 创建新线程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)
# 开启新线程
thread1.start()
thread2.start()
# 添加线程到线程列表
threads.append(thread1)
threads.append(thread2)
# 等待所有线程完成
for t in threads:
t.join()
print "Exiting Main Thread"
5. 线程优先级队列( Queue)
Python的Queue模块中提供了同步的、线程安全的队列类,包括FIFO(先入先出)队列Queue,LIFO(后入先出)队列LifoQueue,和优先级队列PriorityQueue。这些队列都实现了锁原语,能够在多线程中直接使用。可以使用队列来实现线程间的同步。
- Queue模块中的常用方法:
- Queue.qsize() 返回队列的大小
- Queue.empty() 如果队列为空,返回True,反之False
- Queue.full() 如果队列满了,返回True,反之False
- Queue.full 与 maxsize 大小对应
- Queue.get([block[, timeout]])获取队列,timeout等待时间
- Queue.get_nowait() 相当Queue.get(False)
- Queue.put(item) 写入队列,timeout等待时间
- Queue.put_nowait(item) 相当Queue.put(item, False)
- Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号
- Queue.join() 实际上意味着等到队列为空,再执行别的操作
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import Queue
import threading
import time
exitFlag = 0
class myThread (threading.Thread):
def __init__(self, threadID, name, q):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.q = q
def run(self):
print "Starting " + self.name
process_data(self.name, self.q)
print "Exiting " + self.name
def process_data(threadName, q):
while not exitFlag:
queueLock.acquire()
if not workQueue.empty():
data = q.get()
queueLock.release()
print "%s processing %s" % (threadName, data)
else:
queueLock.release()
time.sleep(1)
threadList = ["Thread-1", "Thread-2", "Thread-3"]
nameList = ["One", "Two", "Three", "Four", "Five"]
queueLock = threading.Lock()
workQueue = Queue.Queue(10)
threads = []
threadID = 1
# 创建新线程
for tName in threadList:
thread = myThread(threadID, tName, workQueue)
thread.start()
threads.append(thread)
threadID += 1
# 填充队列
queueLock.acquire()
for word in nameList:
workQueue.put(word)
queueLock.release()
# 等待队列清空
while not workQueue.empty():
pass
# 通知线程是时候退出
exitFlag = 1
# 等待所有线程完成
for t in threads:
t.join()
print "Exiting Main Thread"
三、time
1. time() 函数
time( )函数用于返回当前时间的时间戳(从1970年1月1日00时00分00秒到现在的浮点秒数)
time()函数的语法如下:
- time.time()
- 此语法中第一个 time 表示 time 模块,该函数不需要传递参数
- 返回值:返回当前时间的时间戳
2.localtime([secs]) 函数
time.localtime( )函数的作用是格式化时间戳为本地时间(struct_time类型)。如果secs参数未传入,就以当前时间为转换标准
localtime() 方法的语法:
- time.localtime([ secs ])
- 参数secs -- 指转换为 time.struct_time 类型的对象的秒数
- 返回值:该函数无任何返回值
3.gmtime([secs]) 函数
gmtime( ) 函数用于将一个时间戳转换为UTC时区(0时区)的 struct_time。可选参数 secs 表示从1970-1-1 到现在的秒数,无参数时默认为本地时间
函数返回 time.struct_time 类型的对象 (struct_time 是在 time 模块中定义的表示时间的对象)
gmtime([secs]) 的语法如下:
- time.gmtime([secs])
- 参数secs -- 指转换为 time.struct_time 类型的对象的秒数
- 返回值:该函数无任何返回值
4. sleep(secs) 函数
sleep()函数用于推迟调用线程的运行,可通过参数secs指定进程挂起的时间
sleep()方法的语法:
- time.sleep(t)
- 参数t -- 这是要暂停执行的秒数。
- 返回值:此方法不返回任何值。
5. clock() 函数
clock() 函数用于以浮点数计算的秒数返回当前的 CPU (处理器)时间。用来衡量不同程序的耗时,比time.time()更有用。
该函数在不同的系统上含义不同。在UNIX系统上,它返回的是"进程时间"(unix系统始终返回全部运行时间),它是用秒表示的浮点数(时间戳)。而在Windows中,第一次调用,返回的是进程运行的实际时间。而第二次之后的调用是自第一次调用以后到现在的运行时间.
clock()方法语法:
- time.clock()
- 参数:无
- 返回值:在 win32 系统下,这个函数返回的是真实时间(wall time),而在Unix/Linux下返回的是CPU时间。
四、python读写json文件
- JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它基于ECMAScript的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C、C++、Java、JavaScript、Perl、Python等)。这些特性使JSON成为理想的数据交换语言。易于人阅读和编写,同时也易于机器解析和生成(一般用于提升网络传输速率)。
JSON在python中分别由list和dict组成。
这是用于序列化的两个模块:
- json: 用于字符串和python数据类型间进行转换
- pickle: 用于python特有的类型和python的数据类型间进行转换
Json模块提供了四个功能:dumps、dump、loads、load
pickle模块提供了四个功能:dumps、dump、loads、load
- json dumps把数据类型转换成字符串
- dump把数据类型转换成字符串并存储在文件中
- loads把字符串转换成数据类型
- load把文件打开从字符串转换成数据类型
json是可以在不同语言之间交换数据的,而pickle只在python之间使用。json只能序列化最基本的数据类型,josn只能把常用的数据类型序列化(列表、字典、列表、字符串、数字、),比如日期格式、类对象!josn就不行了。而pickle可以序列化所有的数据类型,包括类,函数都可以序列化。
1.将json 转换成字符串
import json
test_dict = {'bigberg': [7600, {1: [['i111e', 6300], ['222', 800], ['s333', 300]]}]}
print(test_dict)
print(type(test_dict))
#dumps 将数据转换成字符串
json_str = json.dumps(test_dict)
print(json_str)
print(type(json_str))
2.loads: 将 字符串 转换为 字典
new_dict = json.loads(json_str)
print(new_dict)
print(type(new_dict))
3.dump: 将数据写入json文件中
with open("../config/record.json","w") as f:
json.dump(new_dict,f)
print("加载入文件完成...")
4.load:把文件打开,并把字符串变换为数据类型
with open("test.json",'r') as load_f:
load_dict = json.load(load_f)
print(load_dict)
load_dict['smallberg'] = [8200,{1:[[0.1,0.2,0.],[24.3,-19,0.]]}]
print(load_dict)
with open("../config/record.json","w") as dump_f:
json.dump(load_dict,dump_f)
# 五.rospy
## 1.订阅发布话题
1、首先将使用到的话题引入进去
```py
#!/etc/bin/python
#coding=utf-8
import json
import rospy
from std_msgs.msg import Int32
from geometry_msgs.msg import PointStamped
from visualization_msgs.msg import Marker
from geometry_msgs.msg import Point
```
2、与 c++ 类似
```py
rospy.init_node("test", anonymous=True)
#订阅两个话题
rospy.Subscriber("/clicked_point", PointStamped, self.callbackClick)
rospy.Subscriber("/save_pose",Int32,self.callbackSave)
#发布话题
self.path_pub = rospy.Publisher("/path_point",Marker,queue_size = 2)
```
3、回调函数
from geometry_msgs.msg import PointStamped
```py
def callbackClick(self,data):
"""
保存点击的"point"坐标,即将要运行的轨迹
"""
data_list = [round(data.point.x,2),round(data.point.y,2),0.0]
self.pose.append(data_list)
print self.dir + str(self.pose)
```
4、发布话题
两个技巧
- ros::rate
- rospy.is_shutdown()
```py
rate = rospy.Rate(1)
while not rospy.is_shutdown():
mark_line = Marker()
mark_line.header.frame_id = "map"
mark_line.action = Marker.ADD
mark_line.type = Marker.LINE_STRIP
mark_line.scale.x = 0.2
mark_line.color.a = 1
mark_line.color.g = 1
i_index = 0
while i_index < len(self.pose) :
point = Point()
point.x = self.pose[i_index][0]
point.y = self.pose[i_index][1]
mark_line.points.append(point)
i_index +=1
self.path_pub.publish(mark_line)
```
5、利用json保存
```py
with open(self.save_files,"w") as f:
print json.dumps(self.dict_final)
json.dump(self.dict_final,f, indent=4)
print "保存完成: "+ self.save_files
```
## 2 解析数据
6、 rosbag包解析
解析bag包中,两个话题的时间间隔
#!/usr/bin/python
# -*- coding: utf-8 -*-
import rosbag
import rospy
import time
import numpy as np
import matplotlib.pyplot as plt
import sys
if __name__ == '__main__':
front_frame_id = '/base_scan_front'
end_frame_id = '/r2000_node_new/scan'
with rosbag.Bag(sys.argv[1], 'r') as bag:
last_time = rospy.Time()
first = True
front_laser = []
index = 0
end_last_time = rospy.Time()
end_first = True
end_laser = []
end_index = 0
for topic, msg, t in bag.read_messages(topics = [front_frame_id,end_frame_id]):
if topic == front_frame_id:
stamp_sec = msg.header.stamp
if first:
last_time = stamp_sec
first = False
else:
delta_time = (stamp_sec.to_sec() - last_time.to_sec())
if delta_time < 0.07 and delta_time > 0.045:
front_laser.insert(index,delta_time)
last_time = stamp_sec
index = index+1
if topic == end_frame_id:
stamp_sec = msg.header.stamp
if end_first:
end_last_time = stamp_sec
end_first = False
else:
delta_time = (stamp_sec.to_sec() - end_last_time.to_sec())
if delta_time <0.5:
end_laser.insert(end_index,delta_time)
end_last_time = stamp_sec
end_index = end_index+1
print (index,end_index)
plt.figure(figsize=(4, 8))
plt.subplot(2,1,1)
plt.title(front_frame_id, fontsize=14, fontweight='bold')
plt.xlabel('x: (freq)',fontsize=8,fontweight='bold')
plt.ylabel('y:(s)',fontsize=8,fontweight='bold')
plt.plot(front_laser)
plt.grid(True)
plt.subplot(2,1,2)
plt.title(end_frame_id, fontsize=14, fontweight='bold')
plt.xlabel('x: (freq)',fontsize=8,fontweight='bold')
plt.ylabel('y:(s)',fontsize=8,fontweight='bold')
plt.plot(end_laser)
plt.grid(True)
plt.show()