0%

Python 实用方法

一些 Python 的实用方法整理。

各种格式转换

'0102' to b'\x01\x02'

1
2
>>> bytes.fromhex('0102')
b'\x01\x02'

b'\x01\x02' to '0102'

1
2
>>> b'\x01\x02'.hex()
'0102'

b'\x01\x02' to [1, 2]

1
2
>>> list(b'\x01\x02')
[1, 2]

[1, 2] to b'\x01\x02'

1
2
>>> bytes([1, 2])
b'\x01\x02'

b'\x31\x32' to '12'

1
2
>>> b'\x31\x32'.decode()
'12'

'12' to b'\x31\x32'

1
2
>>> '12'.encode()
b'\x31\x32'

0x1234 to b'\x12\x34'

1
2
>>> struct.pack('>H',0x1234)
b'\x12\x34'

或者(推荐)

1
2
a = 0x1234
a.to_bytes(2, 'big)

b'\x12\x34' to 0x1234

1
2
>>> struct.unpack('>H', b'\x12\x34')
(4660,)

或者(推荐)

1
int.from_bytes(b'\x12\x34', 'big')

中文字符导致的错误

Python 文件中若存在中文字符,在执行过程会报错:

1
SyntaxError: Non-ASCII character '\xe4' in file test.py on line 2, but no encoding declared;

Python中默认的编码格式是 ASCII 格式,在没修改编码格式时无法正确打印汉字,所以在读取中文时会报错。

解决方法为只要在文件开头加入# -*- coding: UTF-8 —或者#coding=utf-8就行了。

获取命令行执行结果(成功/失败)

1
2
3
4
5
import subprocess

proc = subprocess.Popen('ps aux', shell=True, stdout=subprocess.PIPE)
ret = proc.wait()
print(ret)

proc.wait() 返回 0 代表成功,返回 1 代表失败

2018-04-06 更新

死锁

关于 wait,官网文档描述如下:

Popen.wait(timeout=None)

Wait for child process to terminate. Set and return returncode attribute.

If the process does not terminate after timeout seconds, raise a TimeoutExpired exception. It is safe to catch this exception and retry the wait.

Note

This will deadlock when using stdout=PIPE or stderr=PIPE and the child process generates enough output to a pipe such that it blocks waiting for the OS pipe buffer to accept more data. Use Popen.communicate() when using pipes to avoid that.

Note

The function is implemented using a busy loop (non-blocking call and short sleeps). Use the asyncio module for an asynchronous wait: see asyncio.create_subprocess_exec.

也就是说,在 stdout/err 定向到 PIPE 后,若子进程的输出超过了 PIPE 大小,那么就会死等 PIPE 被读取,而此时我们的进程又在 wait 内轮询死等子进程结束,所以就造成了死锁。

wait 其实是频繁的轮询子进程结果,等于:

1
2
while proc.poll() != None:
sleep(0.0001)

https://blog.csdn.net/guogaoan/article/details/37034565

那死锁问题如何避免呢?官方文档里推荐使用 Popen.communicate()。这个方法会把输出放在内存,而不是管道里,所以这时候上限就和内存大小有关了,一般不会有问题。而且如果要获得程序返回值,可以在调用 Popen.communicate() 之后取 Popen.returncode 的值。

结论:如果使用 subprocess.Popen,就不使用 Popen.wait(),而使用 Popen.communicate() 来等待外部程序执行结束。

wait() 方式来获取结果有个很大的问题,stdout PIPE buffer是 64K,就是当子进程打印超过时就会卡住,此时死锁就产生了,导致 wait() 始终等不到结果,所以用 communicate 最稳妥。

当然,如果不定向 stdou 到 PIPE,死锁就不会发生。

读取stdout

1
2
3
4
5
p = subprocess.Popen("dir", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
while True:
buff = p.stdout.readline()
if buff == '' and p.poll() != None:
break

stdout 缓冲问题

2018-04-08 更新

http://blog.sina.com.cn/s/blog_4513dde60100oql9.html

PP3E上说过这个问题,说一个程序如果不是以交互的方式运行的话,那么stdout这些都是完全缓冲的,即使设置bufsize也没用,可行的办法是使用pty或者在源码中使用fflush强制flush stdout。

2018-06-24 更新

使用 setbuf 函数关闭 stdout 缓冲区,即可实时输出

1
setbuf(stdout, NULL);

subprocess.Popen 命令类型详解

参考:python中的subprocess.Popen使用

subprocess模块定义了一个类: Popen

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class subprocess.Popen( args, 
bufsize=0,
executable=None,
stdin=None,
stdout=None,
stderr=None,
preexec_fn=None,
close_fds=False,
shell=False,
cwd=None,
env=None,
universal_newlines=False,
startupinfo=None,
creationflags=0)

args参数。可以是一个字符串,可以是一个包含程序参数的列表。要执行的程序一般就是这个列表的第一项,或者是字符串本身。

1
2
subprocess.Popen(["cat","test.txt"])
subprocess.Popen("cat test.txt")

这两个之中,后者将不会工作。因为如果是一个字符串的话,必须是程序的路径才可以。(考虑unix的api函数exec,接受的是字符串
列表)

但是下面的可以工作

1
subprocess.Popen("cat test.txt", shell=True)

这是因为它相当于
subprocess.Popen([“/bin/sh”, “-c”, “cat test.txt”])
在*nix下,当shell=False(默认)时,Popen使用os.execvp()来执行子程序。args一般要是一个【列表】。如果args是个字符串的
话,会被当做是可执行文件的路径,这样就不能传入任何参数了。

在Windows下,下面的却又是可以工作的

1
2
subprocess.Popen(["notepad.exe", "test.txt"])
subprocess.Popen("notepad.exe test.txt")

这是由于windows下的api函数CreateProcess接受的是一个字符串。即使是列表形式的参数,也需要先合并成字符串再传递给api函数
subprocess.Popen("notepad.exe test.txt" shell=True)
等同于
subprocess.Popen("cmd.exe /C "+"notepad.exe test.txt" shell=True

subprocess.run

官方推荐尽量使用 run 方法,如果需要更底层的才使用 Popen

https://docs.python.org/3.5/library/subprocess.html#subprocess.run

The recommended approach to invoking subprocesses is to use the run() function for all use cases it can handle. For more advanced use cases, the underlying Popen interface can be used directly.

其实 run 是对 Popen 和 communicate 以及结果检查的封装

遍历文件夹 - os.walk

1
2
for (root,dirs,files) in os.walk('firmware'):
print(root, dirs, files)

使用国内源来 pip install

https://www.cnblogs.com/microman/p/6107879.html

pip install 默认使用国外源来安装库,但有时奇慢无比,切换到国内源会快很多。

国内源:

新版ubuntu要求使用https源,要注意。

清华:https://pypi.tuna.tsinghua.edu.cn/simple

阿里云:http://mirrors.aliyun.com/pypi/simple/

中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/

华中理工大学:http://pypi.hustunique.com/

山东理工大学:http://pypi.sdutlinux.org/

豆瓣:http://pypi.douban.com/simple/

临时使用:

可以在使用pip的时候加参数-i https://pypi.tuna.tsinghua.edu.cn/simple
例如:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyspider,这样就会从清华这边的镜像去安装pyspider库。

永久修改:

Linux下,修改 ~/.pip/pip.conf (没有就创建一个文件夹及文件。文件夹要加“.”,表示是隐藏文件夹)

1
2
3
4
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
[install]
trusted-host=mirrors.aliyun.com

windows下,直接在user目录中创建一个pip目录,如:C:\Users\xx\pip,新建文件pip.ini。内容同上。

用 pyinstaller 打包 python 脚本到可执行文件

https://jingyan.baidu.com/article/a378c960b47034b3282830bb.html

安装 pyinstaller

1
pip3 install pyinstaller

打包

1
pyinstaller -F your.py

注意:用 -D 来打包到一个目录,运行速度会比 -F 打包到一个 .exe 快。

用 spec files 打包

https://pyinstaller.readthedocs.io/en/v3.3.1/spec-files.html

命令:

1
pyinstaller master.spec

打包资源文件

https://pythonhosted.org/PyInstaller/runtime-information.html#run-time-information

https://pythonhosted.org/PyInstaller/operating-mode.html#how-the-one-file-program-works

有时需要打包一些资源文件,比如图片,音乐,或者可执行文件,需要用 —add-data 选项。

需要注意的是,打包后的可执行文件的工作原理其实是在 /tmp 目录下创建了临时工作文件夹 __MEIxxxxxx

资源文件都是放在此文件夹内的,所以脚本中使用资源文件就必须使用此临时文件夹的路径:sys._MEIPASS

Pyinstaller 和 __import__

__import__可以动态导入模块,在用 pyinstaller 打包时,要把所有可能被导入的模块用 –hidden-import 选项加入进去,否则打包的程序运行时会找不到这些模块。

pip 查看已经安装的包及路径

pip常用命令

1
2
3
显示包所在的目录

pip show -f <包名>

Pycharm + PyQt5 + Qt5 开发

安装 pyqt5

https://www.zhihu.com/question/51562598

用 pip 来安装 pyqt5

1
pip3 install pyqt5

安装 Qt5

http://download.qt.io/official_releases/qt/

下载 5.10.1 版本

配置 PyCharm

Python - Mac下PyQt5环境搭建

信号和槽

https://blog.csdn.net/zhulove86/article/details/52530214

https://blog.csdn.net/a359680405/article/details/45148717

子线程操作 UI

为什么大多数程序子线程都不能刷新UI?

https://blog.csdn.net/AhdaiMolly/article/details/74376525

https://www.2cto.com/kf/201703/608163.html

https://www.v2ex.com/t/346882

signal = pyqtSignal(str)
signal.connect(update) # Main thread
signal.emit(value) # sub thread

UI 线程和 worker 线程之间只能通过 signal 来通信

worker 线程通过 emit signal 来操作 UI。

UI 线程通过 signal connect 的函数来实现回调。

去除标题栏

https://www.cnblogs.com/codeAB/p/5019439.html

1
QWidget.setWindowFlags(Qt.FramelessWindowHint)

全屏

1
QWidget.showFullScreen()

BOX layout 和 Grid layout

QThread

最好不要用 QThread

http://hgoldfish.com/blogs/article/80/

http://www.hgoldfish.com/blogs/article/97/

Progress bar

Progress bar 的高度是由字体决定的

鼠标双击事件

https://blog.csdn.net/dxt1107/article/details/47806965

为了响应双击QLabel的事件,需要重写QWidget的mouseDoubleClickEvent方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4 import *
class MyLabel(QtGui.QLabel):
def __init__(self,parent=None):
super(MyLabel,self).__init__(parent)
def mouseDoubleClickEvent(self,e):
print 'mouse double clicked'
def mousePressEvent(self,e):
print 'mousePressEvent'
def focusInEvent(self,e):
print 'focusInEvent'
def focusOutEvent(self,e):
print 'focusOutEvent'
def moveEvent(self,e):
print 'moveEvent'
def leaveEvent(self,e): #鼠标离开label
print 'leaveEvent'
def enterEvent(self,e): #鼠标移入label
print 'enterEvent'
def mouseMoveEvent(self,e):
print 'mouseMoveEvent'

class TestDialog(QtGui.QDialog):
def __init__(self,parent=None):
super(TestDialog,self).__init__(parent)
self.statusLabel = MyLabel(self)
self.statusLabel.setGeometry(QtCore.QRect(95, 220, 151, 41))
self.statusLabel.setText("hello label")

app=QApplication(sys.argv)
dialog=TestDialog()
dialog.show()

PyQt5 + Qt designer 开发

https://blog.csdn.net/chlk118/article/details/72595325

https://blog.csdn.net/yy123xiang/article/details/78681669

用 Qt designer 生成的 .ui 文件,无需转换成 .py 文件,可以直接用 PyQt5.uic.loadUi 方法来加载。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.uic import loadUi


class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
loadUi('pyflashloader_isp.ui', self)
self.setFixedSize(self.sizeHint())

app = QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec())

文件打开保存框

https://blog.csdn.net/a359680405/article/details/45166271

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QFileDialog

class MyWindow(QtWidgets.QWidget):
def __init__(self):
super(MyWindow,self).__init__()
self.myButton = QtWidgets.QPushButton(self)
self.myButton.setObjectName("myButton")
self.myButton.setText("Test")
self.myButton.clicked.connect(self.msg)

def msg(self):
directory1 = QFileDialog.getExistingDirectory(self,
"选取文件夹",
"C:/") #起始路径
print(directory1)

fileName1, filetype = QFileDialog.getOpenFileName(self,
"选取文件",
"C:/",
"All Files (*);;Text Files (*.txt)") #设置文件扩展名过滤,注意用双分号间隔
print(fileName1,filetype)

files, ok1 = QFileDialog.getOpenFileNames(self,
"多文件选择",
"C:/",
"All Files (*);;Text Files (*.txt)")
print(files,ok1)

fileName2, ok2 = QFileDialog.getSaveFileName(self,
"文件保存",
"C:/",
"All Files (*);;Text Files (*.txt)")

if __name__=="__main__":
import sys

app=QtWidgets.QApplication(sys.argv)
myshow=MyWindow()
myshow.show()
sys.exit(app.exec_())

QWidget 背景透明

1
2
self.setWindowFlag(Qt.FramelessWindowHint)
self.setStyleSheet('background_color:rgba(255,255,255,128)')

其中 FramelessWindowHint 是必须的,没有这个 Flag,背景就不是透明的。

PushButton 对齐边界

PushButton 比较奇怪,放在布局内也会超出一截造成不对齐,所以要单独放在一个布局内,再放入布局内。

比如,先把 pushbutton 放在 vertical layout 内,然后再放在 Grid layout 内,就边界对齐了。

获取本机 MAC 地址

https://www.cnblogs.com/chenjingyi/p/5741742.html

1
2
3
4
import uuid
def get_mac_address():
mac=uuid.UUID(int = uuid.getnode()).hex[-12:]
return ":".join([mac[e:e+2] for e in range(0,11,2)])

需要注意的是,多网卡的机器,此方法返回的 MAC 可能不是固定的。

AES 加密

安装 Crypto 库:

1
pip3 install pycrypto

https://blog.csdn.net/nurke/article/details/77267081

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#coding: utf8
import sys
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex

class prpcrypt():
def __init__(self, key):
self.key = key
self.mode = AES.MODE_CBC

#加密函数,如果text不是16的倍数【加密文本text必须为16的倍数!】,那就补足为16的倍数
def encrypt(self, text):
cryptor = AES.new(self.key, self.mode, self.key)
#这里密钥key 长度必须为16(AES-128)、24(AES-192)、或32(AES-256)Bytes 长度.目前AES-128足够用
length = 16
count = len(text)
if(count % length != 0) :
add = length - (count % length)
else:
add = 0
text = text + ('\0' * add)
self.ciphertext = cryptor.encrypt(text)
#因为AES加密时候得到的字符串不一定是ascii字符集的,输出到终端或者保存时候可能存在问题
#所以这里统一把加密后的字符串转化为16进制字符串
return b2a_hex(self.ciphertext)

#解密后,去掉补足的空格用strip() 去掉
def decrypt(self, text):
cryptor = AES.new(self.key, self.mode, self.key)
plain_text = cryptor.decrypt(a2b_hex(text))
return plain_text.rstrip('\0')

if __name__ == '__main__':
pc = prpcrypt('keyskeyskeyskeys') #初始化密钥
e = pc.encrypt("0123456789ABCDEF")
d = pc.decrypt(e)
print e, d
e = pc.encrypt("00000000000000000000000000")
d = pc.decrypt(e)
print e, d

HASH 算法

1
2
3
>>> import hashlib
>>> hashlib.sha256('123456789'.encode()).hexdigest()
'15e2b0d3c33891ebb0f1ef609ec419420c20e320ce94c65fbc8c3312448eb225'

程序退出 sys.exit(status)

https://www.cnblogs.com/weiman3389/p/6047062.html

sys.exit(status) 的参数 status 就是此代码的执行结果,可以用 subprocess 来捕捉。

移动/删除文件

https://blog.csdn.net/woshisangsang/article/details/74360612

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#文件、文件夹的移动、复制、删除、重命名

#导入shutil模块和os模块
import shutil,os

#复制单个文件
shutil.copy("C:\\a\\1.txt","C:\\b")
#复制并重命名新文件
shutil.copy("C:\\a\\2.txt","C:\\b\\121.txt")
#复制整个目录(备份)
shutil.copytree("C:\\a","C:\\b\\new_a")

#删除文件
os.unlink("C:\\b\\1.txt")
os.unlink("C:\\b\\121.txt")
#删除空文件夹
try:
os.rmdir("C:\\b\\new_a")
except Exception as ex:
print("错误信息:"+str(ex))#提示:错误信息,目录不是空的
#删除文件夹及内容
shutil.rmtree("C:\\b\\new_a")

#移动文件
shutil.move("C:\\a\\1.txt","C:\\b")
#移动文件夹
shutil.move("C:\\a\\c","C:\\b")

#重命名文件
shutil.move("C:\\a\\2.txt","C:\\a\\new2.txt")
#重命名文件夹
shutil.move("C:\\a\\d","C:\\a\\new_d")

threading

daemon

https://www.cnblogs.com/xfiver/p/5189732.html

获取本机 IP 地址

https://blog.csdn.net/weixin_40539892/article/details/79103254

这个方法是目前见过最优雅获取本机服务器的IP方法了。没有任何的依赖,也没有去猜测机器上的网络设备信息。

而且是利用 UDP 协议来实现的,生成一个UDP包,把自己的 IP 放如到 UDP 协议头中,然后从UDP包中获取本机的IP。

这个方法并不会真实的向外部发包,所以用抓包工具是看不到的。但是会申请一个 UDP 的端口,所以如果经常调用也会比较耗时的,这里如果需要可以将查询到的IP给缓存起来,性能可以获得很大提升。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 在 shell 中可以一行调用,获取到本机IP
python -c "import socket;print([(s.connect(('8.8.8.8', 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1])"
10.12.189.16
# 可以封装成函数,方便 Python 的程序调用
import socket

def get_host_ip():
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('8.8.8.8', 80))
ip = s.getsockname()[0]
finally:
s.close()

return ip

requests 加了 timeout 为啥还是会卡住?

https://www.v2ex.com/amp/t/365351

conn = request.urlopen(image_url,timeout=300)

请问有啥优化的办法么?

爬虫爬了 24 小时卡住了。。 重启启动以后又继续爬了


requests 文档上有写
Note
timeout is not a time limit on the entire response download; rather, an exception is raised if the server has not issued a response for timeout seconds (more precisely, if no bytes have been received on the underlying socket for timeout seconds). If no timeout is specified explicitly, requests do not time out.

在最开始加一个
import socket
socket.setdefaulttimeout(时间)
就可以了

Python脚本生成的exe文件自动升级程序实现方法

https://blog.csdn.net/u013193899/article/details/78686039

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import os
import sys
import subprocess

#编写bat脚本,删除旧程序,运行新程序
def WriteRestartCmd(exe_name):
b = open("upgrade.bat",'w')
TempList = "@echo off\n"; #关闭bat脚本的输出
TempList += "if not exist "+exe_name+" exit \n"; #新文件不存在,退出脚本执行
TempList += "sleep 3\n" #3秒后删除旧程序(3秒后程序已运行结束,不延时的话,会提示被占用,无法删除)
TempList += "del "+ os.path.realpath(sys.argv[0]) + "\n" #删除当前文件
TempList += "start " + exe_name #启动新程序
b.write(TempList)
b.close()
subprocess.Popen("upgrade.bat")
sys.exit() #进行升级,退出此程序

def main():
#新程序启动时,删除旧程序制造的脚本
if os.path.isfile("upgrade.bat"):
os.remove("upgrade.bat")
WriteRestartCmd("newVersion.exe")

if __name__ == '__main__':
main()
sys.exit()1234567891011121314151617181920212223242526

代码中不使用os.system()是因为 这个函数会阻塞,等待bat脚本操作完成后,才会继续执行。不适合此处场景

搭建 Flask 服务系统

pip3 install 安装如下:

1
2
3
4
5
6
Flask==0.12.2
Flask-Migrate==2.1.1
Flask-Script==2.0.6
Flask-SQLAlchemy==2.3.2
Flask-Uploads==0.2.1
Flask-WTF==0.14.2

stdout 缓冲区问题

有时候 print 并不能实时打印出来,这时有两种方法:

  1. 在 print 后加 sys.stdout.flush()

  2. 加个 python 选项 -u

    -u **Force stdin, stdout and stderr to be totally **unbuffered. On systems where it matters, also put stdin, stdout and stderr in

https://blog.csdn.net/joeblackzqq/article/details/7220009

使用 Pyinstaller 打包时,可以在 .spec 的 options 内加入 -u 选项:

1
options = [ ('u', None, 'OPTION'), ]

http://pyinstaller.readthedocs.io/en/v3.3.1/spec-files.html?highlight=-u

Python 中 SSH 登录以及 SCP 传输文件

使用 paramiko 库来登录 SSH,使用 scp 来传输文件

http://www.cnblogs.com/haigege/p/5513759.html

http://blog.51cto.com/5ydycm/340854

http://docs.paramiko.org/en/2.4/

https://pypi.org/project/scp

1
2
3
4
5
6
7
8
9
import paramiko
from scp import SCPClient

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.client.MissingHostKeyPolicy)
ssh.connect('192.168.3.40', username='pi', password='snowyang', timeout=2)

with SCPClient(ssh.get_transport()) as scp:
scp.get('/home/pi/mx1290prog/master.log', '40.log')

GitPython

https://www.cnblogs.com/baiyangcao/p/gitpython.html

http://gitpython.readthedocs.io/en/stable/tutorial.html

错误:Text file busy

在调试 B.A.T 烧录器客户端一拖三时发现有时烧录失败但是模组并没有断开,后来看 log 发现是调用 openocd 时发生了问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Info : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : gdb server disabled
shutdown command invoked
/bin/sh: 1: ./openocd: Text file busy
Disconnected
/bin/sh: 1: ./openocd: Text file busy
/bin/sh: 1: ./openocd: Text file busy
Disconnected
/bin/sh: 1: ./openocd: Text file busy
/bin/sh: 1: ./openocd: Text file busy
Disconnected
/bin/sh: 1: ./openocd: Text file busy
/bin/sh: 1: ./openocd: Text file busy
/bin/sh: 1: ./openocd: Text file busy
/bin/sh: 1: ./openocd: Text file busy
Open On-Chip Debugger 0.10.0+dev-00364-g1756f393 (2018-05-03-10:58)
Licensed under GNU GPL v2

起初怀疑是 openocd 不能多进程调用,后来才发现,其实是在烧录时我不小心 CTRL + S 对 .py 文件做了保存操作,也就是说在执行脚本时又写了此脚本,那么就会导致此错误。

参考:https://stackoverflow.com/questions/1384398/usr-bin-perl-bad-interpreter-text-file-busy

对象的生命周期

没有引用,对象就销毁了

一个引用在函数退出后就没有了

函数内的局部对象在退出后就销毁了

https://www.jianshu.com/p/22a8bedc39fd

map 函数返回值问题

https://blog.csdn.net/kairen6645/article/details/80252824

今天在使用python map的过程中,发现了一个奇怪问题,map遍历完成后,再次访问map,发现map为空了。

产生这种差异的原因在于:遍历完最后一个元素后,再次访问时会放回空列表。

所以要把 map 结果转换为 list 再返回:

1
m = list(map(args))

其他

Python奇技淫巧

十六进制字符串转为十六进制数组。

比如把字符串 “ABCDEF” 转为 0xAB, 0xCD, 0xEF。

1
2
3
4
5
6
usr/bin/python

arr = "ABCDEF".decode('hex')
f = open('hex.bin', 'wb')
f.write(arr)
f.close()
坚持原创技术分享,您的支持将鼓励我继续创作!