在这里记一下使用Python过程中比较鸡肋的操作,就是很基础但又容易忘记还不好谷歌的那种操作。
目录
Python模块
重新载入模块
在Python2.X中,可以通过内置函数reload重新载入模块。reload可以在模块被修改的情况下不必关闭Python而重新载入模块。在使用reload重载入模块时,该模块必须事先已经被导入。
在Python3.X中,reload函数已经被删除,要重新再入模块,则必须使用imp模块中的reload函数(如:imp.reload(os) #重新载入os模块)。
Python在哪里查找模块
编写好的模块只有被Python找到才能被导入。
在导入模块时,Python解释器首先在当前目录中查找要导入的模块。如果未找到模块,则Python解释器会从sys模块中path变量指定的目录中查找导入模块。如果在以上所有目录中都未找到导入的模块,则会输出出错信息。
在脚本中可以向sys.path添加模块查找路径:
例如:
import os
import sys
modulepath=os.getcwd()+'\\module' #将当前目录下的module子目录添加到sys.path中
sys.path.append(modulepath)
print(sys.path)
import mymodule #从moudle目录中导入mymoudle模块
是否需要编译模块
当调用或运行完一个模块后,当前目录下会生成一个编译成的字节码文件(.pyc)。
虽然Python是脚本语言,但Python可以将脚本语言编译成字节码的形式。对于模块,Python总是在第一次调用后就将其编译成字节码文件,以提高脚本的启动速度。
对于非模块的脚本,Python不会在运行脚本后将其编译成字节码的形式。如果想将其编译,可以使用py_compile模块:
例如:
#file:bianyi.py
#
import py_compile #导入py_compile模块
py_compile.compile('usemodule.py','usemodule.pyc') #编译 usemodule.py
注意:在Python3中,如果在py_compile.compile函数中不指定第2个参数,则在当前目录新建一个名为“pycache”的目录,并在这个目录中生成“被编译模块名.cpython-32.pyc”的pytc字节码文件。
脚本优化编译
可以通过Python的命令行选项将脚本优化编译。Python编译的优化选项有两个:
-O 该选项对脚本的优化不多,编译后的脚本以“.pyo”为扩展名。凡是以“.pyo”为扩展名的Python字节码都是经过优化的。
-OO 该选项对脚本的优化的程度很大。使用该标志可以使编译的Python脚本更小。使用该选项可以导致脚本运行错误,因此,谨慎使用。
例如:
>>>python -O compile.py
>>>python -OO compile.py
如何查看模块提供的函数名
使用内置函数dir()来查看
dir([object]) #object 可选参数,要列举的模块名
例如:
>>>import os
>>>dir(os) #获得os模块中的名字和函数
或者:
>>>dir() #获得当前脚本中所有名字列表
Psyco让 Python 运行得像 C 一样快
用 Psyco 让 Python 运行得像 C 一样快。
这玩意儿没用过,只是听说过,以后用到了再学习补充。
参考文章:
https://www.ibm.com/developerworks/cn/linux/sdk/python/charm-28/
得到列表中唯一元素值的最快方法set([1,1])
a = [1,2,3,3,4,5,5,5,5,6]
b = set(a)
b
Python线程
线程概念
几个概念:
- 线程 — 是程序的执行分支,是程序中真正负责执行业务的地方。
- 多线程 — 类似于同时执行多个不同的程序。
- 并发 — 四百米接力赛
- 并行 — 跑马拉松
优点:
- 可以把那些长时间处于等待的线程,放到后台去处理。 下载内容。等待文件。等待网络请求。等待数据库
- 给前端增加一些额外的特效。如:下载进度、触发事件(手机上点击某个应用的图标)。
- 让程序的执行速度更快。如:多线程下载(相当于空间换时间)
线程是包含于进程的。每个线程都有自己的CPU寄存器。称之为线程的上下文,用于反应线程上次运行的状态
Pyhon中的两种线程
Python中包含两种线程:
- 内核线程 — 由操作系统内核创建和撤销的。
- 用户线程 — 由用户创建和撤销的。
Python3中的两个线程模块
- threading(推荐使用)
- _thread
在低版本是有thread模块的,但在python3被废弃了,使用_thread来代替。
threading提供了几个函数:
thrading.currentThread() #获取当前线程变量
thrading.enumerate() #获取包含当前正在运行的线程的集合(list[]格式)
thrading.activeCount() #获取当前存活的线程数量,和len(thrading.enumerate())一样。
Thread类还提供如下函数:
run() # 线程活动的方法
start() #启动线程
join() #等待至线程中止。 A和B Bjoin A 让A等待。
isAlive() #判断线程是否存活
getName() #获取线程名称
Python中创建线程的两种方法
- 用类来包装线程对象(推荐使用)
- 用函数
_thread 提供了低级别的原始的以及简单的锁,不完全,因此它的功能相比threading有限。
1、用类包装线程对象创建线程(推荐使用)
例如:
import threading
import time
# 设置一个标志。
exitFlag = 0
# 创建一个数据类型。名字叫做myThread. 该类型继承threading模块中的Thread类。
class myThread(threading.Thread):
# 构造方法 用于构造myThread对象。 myThread类型的值。类似于i = 0
def __init__(self, threadID, name, counter):
# 调用父类的构造
threading.Thread.__init__(self)
# 完成参数赋值
self.name = name
self.threadID = threadID
self.counter = counter
# 重写的方法。线程实际执行的业务都必须放在这。
def run(self):
print("开始线程:{}".format(self.name))
print_curr_time(self.name, self.counter, 5)
print("结束线程:{}".format(self.name))
def print_curr_time(name, delay,counter):
"""
用于打印当前时间
:param name: 线程的名称
:param delay: 延迟的时间
:return:
"""
while counter:
# 让当前休眠。休眠delay的时间
if exitFlag:
name.exit()
time.sleep(delay)
print("{}\t{}".format(name, time.ctime(time.time())))
counter -= 1
# 创建新线程
thread1 = myThread(1,"一只王八",1)
thread2 = myThread(2,"岂不美哉",2)
# 启动线程
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print("退出主线程")
执行结果:
开始线程:一只王八
开始线程:岂不美哉
一只王八 Fri Dec 28 17:50:06 2018
岂不美哉 Fri Dec 28 17:50:07 2018
一只王八 Fri Dec 28 17:50:07 2018
一只王八 Fri Dec 28 17:50:08 2018
岂不美哉 Fri Dec 28 17:50:09 2018
一只王八 Fri Dec 28 17:50:09 2018
一只王八 Fri Dec 28 17:50:10 2018
结束线程:一只王八
岂不美哉 Fri Dec 28 17:50:11 2018
岂不美哉 Fri Dec 28 17:50:13 2018
岂不美哉 Fri Dec 28 17:50:15 2018
结束线程:岂不美哉
退出主线程
线程锁的用法
上面执行结果顺序有点“乱”,想要让线程按规定顺序执行的话就需要用到“锁”了。
这里的“锁”并不是指给资源加锁,而是用锁去锁定资源,你可以定义多个锁, 当你需要独占某一资源时,任何一个锁都可以锁这个资源。这和你用不同的锁都可以把相同的一个门锁住是一个道理。
【注意】这个锁是不被某个特定线程所拥有的。一个线程获取了锁,之后任何线程尝试着获取锁,都会失败,包括这个获取了锁的线程自己尝试获取锁。
#创建锁
mutex = threading.Lock()
#锁定
mutex.acquire(blocking = True, timeout = -1)
"""
返回的是True或者False,分别代表成功和失败。
默认的两个参数:
1、blocking=True,意思是调用方法的时候没有获取到锁,就会堵塞线程,直到获取到锁为止。
2、timeout=-1,表示等待获取锁的时间,-1表示一直等待。如果超过timeout设定的时间还没有获取到锁就会返回获取锁失败。
【注意】如果设定了timeout为正数,则不能设定blocking=False。因为设定了timeout为正数表明等待设定的时间会阻塞线程,和blocking=False是矛盾的。
"""
#释放
mutex.release()
代码举栗:
交替打印ABC,A由一个线程打印 ,B由一个线程打印,C由一个线程打印。
import threading
def work_1():
for i in range(5):
mutex1.acquire()
print("A")
try:
mutex2.release()
except:
pass
def work_2():
for i in range(5):
mutex2.acquire()
print("B")
try:
mutex3.release()
except:
pass
def work_3():
for i in range(5):
mutex3.acquire()
print("C")
try:
mutex1.release()
except:
pass
if __name__ == '__main__':
mutex1 = threading.Lock()
mutex2 = threading.Lock()
mutex3 = threading.Lock()
t1 = threading.Thread(target=work_1)
t2 = threading.Thread(target=work_2)
t3 = threading.Thread(target=work_3)
t1.start()
t2.start()
t3.start()
t1.join()
t2.join()
t3.join()
执行结果:
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
关于锁还有一些内容,可以参考一下这篇文章:《threading中的锁》
2、函数式创建线程
_thread.start_new_thread(function,args,[kwargs])
# function: 线程函数
# args:传递给线程的参数。必须是tuple类型
# []代表可选
例如:
import _thread
import time
def print_curr_time(name,delay):
"""
用于打印当前时间
:param name: 线程的名称
:param delay: 延迟的时间
:return:
"""
count = 0
while count < 5:
# 让当前休眠。休眠delay的时间
time.sleep(delay)
count += 1
print("{}\t{}".format(name,time.ctime(time.time())))
# 创建线程
try:
#括号内放的是希望thread去执行的函数
_thread.start_new_thread(print_curr_time ,("Thread-1",2))
_thread.start_new_thread(print_curr_time ,("Thread-2",4))
except Exception:
print("Error: 无法启动线程")
执行结果如下:
Thread-1 Fri Dec 28 17:38:24 2018
Thread-2 Fri Dec 28 17:38:26 2018
Thread-1 Fri Dec 28 17:38:26 2018
Thread-1 Fri Dec 28 17:38:28 2018
Thread-2 Fri Dec 28 17:38:30 2018
Thread-1 Fri Dec 28 17:38:30 2018
Thread-1 Fri Dec 28 17:38:32 2018
Thread-2 Fri Dec 28 17:38:34 2018
Thread-2 Fri Dec 28 17:38:38 2018
Thread-2 Fri Dec 28 17:38:42 2018
故障
Anaconda使用时出现的代理错误解决办法
刚才想用conda创建一个虚拟环境,结果老是出现代理错误,如下图:
以前遇到这种情况,一般是换个好点的网速,或者换个镜像。然而这次并没什么用。仔细一看才知道是代理有错。
解决方案如下:
右击桌面的网络图标–>属性–>选择“连接”选项卡;
找到局域网设置,把下面的代理服务器勾号去掉,改为“自动检测设置”打勾。应用即可。
总是出现python库安装不上的情况
安装python库的时候可能会出现以下情况:
勾去代理的方法也不管用,而且安装其他的python库也会出现这种情况。
解决方案1:
找到internet选项重置一下:
解决方案2:
换一个连接
Python的函数参数按值还是按引用传递参数?
详情见官方文档:
http://www.runoob.com/python/python-functions.html
这里只说一个我碰到的例子:
def tst(a):
a.append([1,2,3])
print('函数tst中的列表a是:',a)
pass
x = ['q','w','e']
tst(x)
print('函数tst外的列表x是:',x)
输出:
函数tst中的列表a是: ['q', 'w', 'e', [1, 2, 3]]
函数tst外的列表x是: ['q', 'w', 'e', [1, 2, 3]]
从上面现象我们知道,函数在改变形参a
的同时居然也把实参x
也给改变了!
然后我又去找了一些资料才知道,在python中,strings, tuples, 和numbers是不可更改的对象,而list,dict等则是可以修改的对象。
然后我又试了一下numpy.array
,也是可修改的。
如果想在改变形参的同时又不改变实参,可以这么做:
def tst(a_):
a = a_.copy() #copy一下形参接受到的值并赋给变量a
a.append([1,2,3])
print('函数tst中的列表a是:',a)
pass
x = ['q','w','e']
tst(x)
print('函数tst外的列表x是:',x)
输出结果:
函数tst中的列表a是: ['q', 'w', 'e', [1, 2, 3]]
函数tst外的列表x是: ['q', 'w', 'e']