本文共 8984 字,大约阅读时间需要 29 分钟。
例一
import _threadimport 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: 无法启动线程")while 1: pass
例二:
import _threadfrom time import sleepfrom datetime import datetimedate_time_format='%y-%M-%d %H:%M:%S'def date_time_str(date_time): return datetime.strftime(date_time, date_time_format)def loop_one(): print(f'+++线程一开始于:{ date_time_str(datetime.now())}') print('+++线程一休眠4秒') sleep(4) print(f'+++线程一休眠结束,结束于:{ date_time_str(datetime.now())}')def loop_two(): print(f'***线程二开始时间:{ date_time_str(datetime.now())}') print('***线程二休眠2秒') sleep(2) print(f'***线程二休眠结束,结束时间:{ date_time_str(datetime.now())}')def main(): print(f'------所有线程开始时间:{ date_time_str(datetime.now())}') _thread.start_new_thread(loop_one, ()) _thread.start_new_thread(loop_two, ()) sleep(6) print(f'------所有线程结束时间:{ date_time_str(datetime.now())}')if __name__ == '__main__': main()主线程一旦运行结束,就关闭运行着的其他两个线程。这可能造成主线程过早或过晚退出,这时就要使用线程锁,主线程可以在两个子线程都退出后立即退出。 示例代码如下
import _threadfrom time import sleepfrom datetime import datetimeloops=[4, 2]date_time_format='%y-%M-%d %H:%M:%S'def date_time_str(date_time): return datetime.strftime(date_time, date_time_format)def loop(n_loop, n_sec, lock): print(f'线程({ n_loop})开始执行:{ date_time_str(datetime.now())},先休眠({ n_sec})秒') sleep(n_sec) print(f'线程({ n_loop})休眠结束,结束于:{ date_time_str(datetime.now())}') lock.release()def main(): print('---所有线程开始执行...') locks=[] n_loops=range(len(loops)) for i in n_loops: lock=_thread.allocate_lock() lock.acquire() locks.append(lock) for i in n_loops: _thread.start_new_thread(loop, (i, loops[i], locks[i])) for i in n_loops: while locks[i].locked(): pass print(f'---所有线程执行结束:{ date_time_str(datetime.now())}')if __name__ == '__main__': main()
例子:
import threadingfrom time import sleepfrom datetime import datetimeloops=[4, 2]date_time_format='%y-%M-%d %H:%M:%S'def date_time_str(date_time): return datetime.strftime(date_time, date_time_format)def loop(n_loop, n_sec): print(f'线程({ n_loop})开始执行:{ date_time_str(datetime.now())},先休眠({ n_sec})秒') sleep(n_sec) print(f'线程({ n_loop})休眠结束,结束于:{ date_time_str(datetime.now())}')def main(): print(f'---所有线程开始执行:{ date_time_str(datetime.now())}') threads=[] n_loops=range(len(loops)) for i in n_loops: t=threading.Thread(target=loop, args=(i, loops[i])) threads.append(t) for i in n_loops: # start threads threads[i].start() for i in n_loops: # wait for all threads[i].join() # threads to finish print(f'---所有线程执行结束于:{ date_time_str(datetime.now())}')if __name__ == '__main__': main()附自己修改后的代码:
import threadingfrom time import sleepfrom datetime import datetimeloops=[2, 2]date_time_format='%y-%M-%d %H:%M:%S'def date_time_str(date_time): return datetime.strftime(date_time, date_time_format)def loop(n_loop, n_sec): print(f'线程({ n_loop})开始执行:{ date_time_str(datetime.now())},先休眠({ n_sec})秒') sleep(n_sec) print(f'线程({ n_loop})休眠结束,结束于:{ date_time_str(datetime.now())}')def begin(n_loop,sec): print(f'线程{ n_loop}开始执行:{ date_time_str(datetime.now())}') print("begin") sleep(sec) print(f'{ n_loop}休眠结束,结束于:{ date_time_str(datetime.now())}')def main(): print(f'---所有线程开始执行:{ date_time_str(datetime.now())}') threads=[] n_loops=range(len(loops)) t=threading.Thread(target=loop, args=(1, loops[0])) threads.append(t) m=threading.Thread(target=begin,args=(2,loops[1])) threads.append(m) for i in n_loops: # start threads threads[i].start() for i in n_loops: # wait for all threads[i].join() # threads to finish print(f'---所有线程执行结束于:{ date_time_str(datetime.now())}')if __name__ == '__main__': main()
如果多个线程共同修改某个数据,就可能会出现不可预料的结果。为了保证数据的正确性,需要对多个线程进行同步。 使用Thread对象的Lock和RLock可以实现简单的线程同步,这两个对象都有acquire方法和release方法。对于每次只允许一个线程操作的数据,可以将操作放到acquire和release方法之间。 多线程的优势在于可以同时运行多个任务,但当线程需要共享数据时,可能存在数据不同步的问题。 考虑这样一种情况:一个列表里所有元素都是0,线程set从后向前把所有元素改成1,而线程print负责从前往后读取列表并输出。
线程set开始改的时候,线程print可能就来输出列表了,输出就成了一半0一半1,这就是数据不同步的问题。为了避免这种情况,引入了锁的概念。 锁有两种状态——锁定和未锁定。当一个线程(如set)要访问共享数据时,必须先获得锁定;如果已经有别的线程(如print)获得锁定了,就让线程set暂停,也就是同步阻塞;等到线程print访问完毕,释放锁以后,再让线程set继续。 经过这样的处理,输出列表时要么全部输出0,要么全部输出1,不会再出现一半0一半1的尴尬场面。示例代码:
import threadingfrom time import sleepfrom datetime import datetime date_time_format='%y-%M-%d %H:%M:%S' 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(f"开启线程: { self.name}") # 获取锁,用于线程同步 threadLock.acquire() print_time(self.name, self.counter, 3) # 释放锁,开启下一个线程 threadLock.release() def date_time_str(date_time): return datetime.strftime(date_time, date_time_format) def print_time(threadName, delay, counter): while counter: sleep(delay) print(f"{ threadName}: { date_time_str(datetime.now())}") counter -= 1 def main(): # 创建新线程 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("退出主线程") if __name__ == "__main__": threadLock=threading.Lock() threads=[] main()
增加和查询操作:
import pymysqlimport timepymysql.install_as_MySQLdb()from sqlalchemy import create_engine,text#定义数据库属性hostname = '127.0.0.1'port = '3308'database = 'data1'username = 'heziyi'pwd = '123456'dburl = 'mysql+mysqldb://{}:{}@{}:{}/{}'.format(username,pwd,hostname,port,database)timenow= time.strftime('%Y-%m-%d',time.localtime(time.time()))print(timenow)#创建数据库连接对象engine = create_engine(dburl,echo=True)with engine.connect() as con: # rs = con.execute('SELECT 1') # con.execute(text("select 1 ")) sql = 'INSERT INTO data1.wash VALUES(10,\'15\',\'175\',\'9\',\'19.4\',\'2021-05-24\');' result = con.execute(sql ) result = con.execute('select * from wash') print(result.fetchall())查询某一列:
result = con.execute('select times,average,Time from wash') print(result.fetchall())
结果:
[(‘4’, 30.5, datetime.date(2021, 5, 18)), (‘5’, 28.4, datetime.date(2021, 5, 20)), (‘6’, 26.7, datetime.date(2021, 5, 21)), (‘7’, 26.0, datetime.date(2021, 5, 22)), (‘8’, 25.7, datetime.date(2021, 5, 23)), (‘9’, 19.4, datetime.date(2021, 5, 24))]格式化插入(传入变量的方式):
timenow= time.strftime('%Y-%m-%d',time.localtime(time.time()))#创建数据库连接对象engine = create_engine(dburl,echo=True)with engine.connect() as con: sql = 'INSERT INTO data1.wash VALUES(11,\'15\',\'175\',\'9\',\'19.4\',\'{}\');'.format(timenow)
多个格式化
‘b’ - 二进制。将数字以2为基数进行输出。
‘c’ - 字符。在打印之前将整数转换成对应的Unicode字符串。 ‘d’ - 十进制整数。将数字以10为基数进行输出。 ‘o’ - 八进制。将数字以8为基数进行输出。 ‘x’ - 十六进制。将数字以16为基数进行输出,9以上的位数用小写字母。 ‘e’ - 幂符号。用科学计数法打印数字。用’e’表示幂。 ‘g’ - 一般格式。将数值以fixed-point格式输出。当数值特别大的时候,用幂形式打印。 ‘n’ - 数字。当值为整数时和’d’相同,值为浮点数时和’g’相同。不同的是它会根据区域设置插入数字分隔符。 ‘%’ - 百分数。将数值乘以100然后以fixed-point(‘f’)格式打印,值后面会有一个百分号。print('{0:b}'.format(3))print('{0:d}'.format(3))print('{0:o}'.format(3))print('{0:x}'.format(3))name = ‘jack’ age = 18 sex = ‘man’ job = “IT” salary = 9999.99
print(f’my name is {name.capitalize()}.’)
print(f’I am {age:*^10} years old.’) print(f’I am a {sex}’) print(f’My salary is {salary:10.3f}’)结果
my name is Jack. I am 18 years old. I am a man My salary is 9999.990关于python运行多线程的问题:
1)Python多线程的效率怎么样? 答:Python有全锁局的存在(同一时间只能有一个线程执行),并不能利用多核优势。如果你的多线程进程是CPU密集型的,多线程就不能带来效率的提升,相反还可能因为线程的频繁切换导致效率下降。如果是IO密集型,多线程进程就可以利用IO阻塞等待时的空闲时间执行其他线程,从而提升效率。 (2)既然Python解释器是单线程的,还有进行多线程编程的必要吗? 答:多线程最开始不是用来解决多核利用率问题的,而是用来解决IO占用时CPU闲置的问题。 多线程可以用来解决阻塞问题,可以做事件响应机制(或者类似信号槽的问题)。如果运行瓶颈不是在CPU运算而是在IO(网络)上,多线程显然很划算。 能产生IO阻塞的情况很多,如网络、磁盘等。当发生阻塞时,Python是不耗CPU的,此时如果只有一个线程就没法处理其他事情了。对于有IO阻塞的环境,多线程可能让你的CPU跑到100%。 另一个用处来自于Python的C扩展模块。在扩展模块里可以释放GIL。释放GIL期间不应该调用任何Python API。对于一些非常繁重的计算,可以写成C模块,计算前释放GIL,计算后重新申请GIL,并将结果返回给Python。这样就可以让Python进程利用更多CPU资源。每个Python线程都是OS级别的Pthread线程。利用Python管理这些线程比在C层级操作Pthread更方便。转载地址:http://ntten.baihongyu.com/