-
开始码代码之前,我们先来了解一下三种邮件服务协议:1、SMTP协议SMTP(Simple Mail Transfer Protocol),即简单邮件传输协议。相当于中转站,将邮件发送到客户端。2、POP3协议POP3(Post Office Protocol 3),即邮局协议的第3个版本,是电子邮件的第一个离线协议标准。该协议把邮件下载到本地计算机,不与服务器同步,缺点是更易丢失邮件或多次下载相同的邮件。3、IMAP协议IMAP(Internet Mail Access Protocol),即交互式邮件存取协议。该协议连接远程邮箱直接操作,与服务器内容同步。然后介绍一下email包这个包的中心组件是代表电子邮件消息的“对象模型”。 应用程序主要通过在 message 子模块中定义的对象模型接口与这个包进行交互。 应用程序可以使用此 API 来询问有关现有电子邮件的问题、构造新的电子邮件,或者添加或移除自身也使用相同对象模型接口的电子邮件子组件。 也就是说,遵循电子邮件消息及其 MIME 子组件的性质,电子邮件对象模型是所有提供 EmailMessage API 的对象所构成的树状结构。接下来我们通过具体的代码实现一个登录邮箱客户端,下载邮件,解析邮件附件内容的功能。首先我们需要定义一个邮件解析的类,该类需要三个变量:1、邮箱所属的imap服务地址;2、邮箱账号;3、邮箱密码【注:不同邮箱需要不同的安全策略,例如qq邮箱需要短信验证,获取登录授权码,而不是明文密码去登录远程客户端】123456789class Email_parse: def __init__(self,remote_server_url,email_url,password): # imap服务地址 self.remote_server_url = remote_server_url # 邮箱账号 self.email_url = email_url # 邮箱密码 self.password = password然后定义类中入口函数,登录远程,默认获取第一页所有的邮件。我们获取邮件的主题,并打印出来【不同邮件主题的编码可能不同,二进制需要转码才能正确显示】12345678910111213141516171819202122def main_parse_Email(self): """入口函数,登录imap服务""" server = imaplib.IMAP4_SSL(self.remote_server_url, 993) server.login(self.email_url, self.password) server.select('INBOX') status,data = server.search(None,"ALL") if status != 'OK': raise Exception('read email error') emailids = data[0].split() mail_counts = len(emailids) print("count:",mail_counts) # 邮件的遍历是按时间从后往前,这里我们选择最新的一封邮件 for i in range(mail_counts - 1, mail_counts - 2, -1): status, edata = server.fetch(emailids[i], '(RFC822)') msg = email.message_from_bytes(edata[0][1]) #获取邮件主题title subject = email.header.decode_header(msg.get('subject')) if type(subject[-1][0]) == bytes: title = subject[-1][0].decode(str(subject[-1][1])) elif type(subject[-1][0]) == str: title = subject[-1][0] print("title:", title)其中,msg变量保存的就是邮件的主体,接下来因为会重复用到msg和tilte,我们将构造一个类函数返回msg和title。12345678def get_email_title(msg): subject = email.header.decode_header(msg.get('subject')) if type(subject[-1][0]) == bytes: title = subject[-1][0].decode(str(subject[-1][1])) elif type(subject[-1][0]) == str: title = subject[-1][0] print("title:", title) return title解析邮件,我们分为两部分,邮件正文【HTML】和附件【xlsx等】,判断有附件,我们就保存到固定的路径下。表格的解析不再赘述了,pandas之类的包足以搞定。12345678910111213def get_att(msg): """获取附件并下载""" filename = Email_parse.get_email_name(msg) for part in msg.walk(): file_name = part.get_param("name") if file_name: data = part.get_payload(decode=True) if data != None: att_file = open('./src/' + filename, 'wb') att_file.write(data) att_file.close() else: pass邮件正文内容,我们直接解析html,将文本内容直接保存到.txt文件中,方便读取。12345678910111213def get_text_from_HTML(msg): """获取邮件中的html""" filename = Email_parse.get_email_name(msg) current_title = Email_parse.get_email_title(msg) print("filename:",filename,type(filename)) for part in msg.walk(): if not part.is_multipart(): result = part.get_payload(decode=True) result = result.decode('gbk') f = open(f'./src/{current_title}.txt','w') f.write(result) f.close() return result完整代码如下:123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293import emailimport imaplibfrom email.header import decode_headerimport pandas as pdimport datetime class Email_parse: def __init__(self,remote_server_url,email_url,password): self.remote_server_url = remote_server_url self.email_url = email_url self.password = password def get_att(msg): filename = Email_parse.get_email_name(msg) for part in msg.walk(): file_name = part.get_param("name") if file_name: data = part.get_payload(decode=True) if data != None: att_file = open('./src/' + filename, 'wb') att_file.write(data) att_file.close() else: pass def get_email_title(msg): subject = email.header.decode_header(msg.get('subject')) if type(subject[-1][0]) == bytes: title = subject[-1][0].decode(str(subject[-1][1])) elif type(subject[-1][0]) == str: title = subject[-1][0] print("title:", title) return title def get_email_name(msg): for part in msg.walk(): file_name = part.get_param("name") if file_name: h = email.header.Header(file_name) dh = email.header.decode_header(h) filename = dh[0][0] if dh[0][1]: value, charset = decode_header(str(filename, dh[0][1]))[0] if charset: filename = value.decode(charset) print("附件名称:", filename) return filename def main_parse_Email(self): server = imaplib.IMAP4_SSL(self.remote_server_url, 993) server.login(self.email_url, self.password) server.select('INBOX') status,data = server.search(None,"ALL") if status != 'OK': raise Exception('read email error') emailids = data[0].split() mail_counts = len(emailids) print("count:",mail_counts) for i in range(mail_counts - 1, mail_counts - 2, -1): status, edata = server.fetch(emailids[i], '(RFC822)') msg = email.message_from_bytes(edata[0][1]) subject = email.header.decode_header(msg.get('subject')) if type(subject[-1][0]) == bytes: title = subject[-1][0].decode(str(subject[-1][1])) elif type(subject[-1][0]) == str: title = subject[-1][0] print("title:", title) Email_parse.get_att(msg) Email_parse.get_text_from_HTML(msg) def get_text_from_HTML(msg): filename = Email_parse.get_email_name(msg) current_title = Email_parse.get_email_title(msg) print("filename:",filename,type(filename)) for part in msg.walk(): if not part.is_multipart(): result = part.get_payload(decode=True) result = result.decode('gbk') f = open(f'./src/{current_title}.txt','w') f.write(result) f.close() return result if __name__ == "__main__": remote_server_url = 'imap.qq.com' email_url = "*********@qq.com" password = "**********" demo = Email_parse(remote_server_url,email_url,password) demo.main_parse_Email()
-
目录一、需求描述二、首先扫码登录获取cookies保存到本地未后面免密登录做准备三、初始化浏览器四、获取本地保存的cookies实现登录一、需求描述web 自动化测试/python爬虫往往会遇到扫码登录的情况,不是所有的网站都支持用户密码登录,遇到这种扫码登录的情况会阻碍我们自动化测试/爬虫的进行,所有为了可以顺畅的进行我们的需求,在进行自动化或者爬虫前我们首先要解决扫码登录的问题,下面讲解如何实现扫码免密登录。二、首先扫码登录获取cookies保存到本地未后面免密登录做准备具体实现代码如下:12345678910111213141516def get_cookies(): # 首先获取cookies保存至本地 driver = webdriver.Chrome('/Users/xxx/Documents/python/pack/chromedriver/chromedriver') page_url = 'https:/xxx/38268919/bugtrace/buglists/query/1/created/desc?query_token=20220706291334df28c613a85aa589f04376d034' driver.get(page_url) driver.maximize_window() # 进行扫码登录 time.sleep(20) # 获取列表形式的cookies cookies = driver.get_cookies() # 转换成字符串保存 jsonCookie = json.dumps(cookies) # 保存到txt文件 with open('cookies.txt','w') as f: f.write(jsonCookie) print('cookies保存成功!')三、初始化浏览器123456def browser_initial(): driver = webdriver.Chrome('/Users/xxx/Documents/python/pack/chromedriver/chromedriver') page_url = 'https://xxx/38268919/bugtrace/buglists/query/1/created/desc?query_token=20220706291334df28c613a85aa589f04376d034' driver.get(page_url) driver.maximize_window() return driver四、获取本地保存的cookies实现登录代码实现如下123456789101112131415161718def login(driver): with open('cookies.txt','r',encoding='utf8') as f: cookies = json.loads(f.read()) # 给浏览器添加cookies for cookie in cookies: cookie_dict = { 'domain': '.tapd.cn', 'name': cookie.get('name'), 'value': cookie.get('value'), "expiry": 1658386136, 'path': '/', 'httpOnly': True, 'Secure': True } # print(cookie_dict) driver.add_cookie(cookie_dict) # 刷新网页,cookies才会成功 driver.refresh()12345if __name__ =='__main__': driver=browser_initial() login(driver)
-
在日常工作中,PPT制作是常见的工作,如果制作创意类PPT,则无法通过自动化的形式生成,因为创意本身具有随机性,而自动化解决的是重复性工作,两者有所冲突。python-pptx是python处理PPT的一个库,注重的是读和写,无法导出,没有渲染功能。废话不多说,第一步,安装python-pptx库:1pip3 install -i https://pypi.doubanio.com/simple/ python-pptxppt里面处理的主要对象一般为文本框,表格,图片。每一页的ppt为一个slide123456from pptx import Presentation, utilfrom pptx.util import Pt,Cmfrom pptx.shapes.picture import Picture#实例化一个ppt对象ppt = Presentation("./test.pptx")slide = ppt.slides[0] #第几页然后遍历查看这一页ppt中都包含哪些对象:123456789101112131415161718192021222324252627282930313233def rander_template(slide): for shape in slide.shapes: if shape.has_text_frame == True: print("==========================文本框=============================") print("段落长度:",len(shape.text_frame.paragraphs)) for paragraph in shape.text_frame.paragraphs: # 拼接文字 print("段落包含字段:",len(paragraph.runs)) print(''.join(run.text for run in paragraph.runs)) for i in range(len(paragraph.runs)): print("run"+str(i)+":"+paragraph.runs[i].text) print(shape.text_frame.paragraphs[0].runs[0].text) shape.text_frame.paragraphs[0].runs[0].text = "规则是自由的第一要义" elif shape.has_table == True: print("==========================表格==============================") one_table_data = [] for row in shape.table.rows: # 读每行 row_data = [] for cell in row.cells: # 读一行中的所有单元格 cell.text = cell.text if cell.text != "" else "未填写" c = cell.text row_data.append(c) one_table_data.append(row_data) # 把每一行存入表 # 用二维列表输出表格行和列的数据 print(one_table_data) print("第一个单元格内容:",shape.table.rows[0].cells[0].text) elif isinstance(shape,Picture): print("==========================图片==============================") index = 0 with open(f'{index}.jpg','wb') as f: f.write(shape.image.blob) index += 1文本框对象【text_frame】:shape.has_text_frame查看是否有文本框对象,有的话查看具体有几个段落【len(shape.text_frame.paragraphs)】,每个段落又有多少个run对象【len(paragraph.runs)】注意:修改run对象的时候,修改run[0],后面的值都会被覆盖。表格对象【table】:table对象还是按照行列值来定位划分的,eg:table.rows[2]cells[3].text代表第三行第四列的值图片对象【Picture】:插入图片需要固定图片的位置,比如:def insert_pic(slide): #需要用到pptx库的util方法 img_path = './blue.png' # 图片路径 # 设置图片的位置和大小 left = util.Cm(8.04) top = util.Cm(9.93) width = util.Cm(15.07) height = util.Cm(4.06) # 在页面中插入图片 slide.shapes.add_picture(img_path, left, top, width, height)全部代码:123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354from pptx import Presentation, utilfrom pptx.util import Pt,Cmfrom pptx.shapes.picture import Pictureppt = Presentation("./test.pptx") def rander_template(slide): for shape in slide.shapes: if shape.has_text_frame == True: print("==========================文本框=============================") print("段落长度:",len(shape.text_frame.paragraphs)) for paragraph in shape.text_frame.paragraphs: # 拼接文字 print("段落包含字段:",len(paragraph.runs)) print(''.join(run.text for run in paragraph.runs)) for i in range(len(paragraph.runs)): print("run"+str(i)+":"+paragraph.runs[i].text) print(shape.text_frame.paragraphs[0].runs[0].text) shape.text_frame.paragraphs[0].runs[0].text = "规则是自由的第一要义" elif shape.has_table == True: print("==========================表格==============================") one_table_data = [] for row in shape.table.rows: # 读每行 row_data = [] for cell in row.cells: # 读一行中的所有单元格 cell.text = cell.text if cell.text != "" else "未填写" c = cell.text row_data.append(c) one_table_data.append(row_data) # 把每一行存入表 # 用二维列表输出表格行和列的数据 print(one_table_data) print("第一个单元格内容:",shape.table.rows[0].cells[0].text) elif isinstance(shape,Picture): print("==========================图片==============================") index = 0 with open(f'{index}.jpg','wb') as f: f.write(shape.image.blob) index += 1def insert_pic(slide): img_path = './blue.png' # 图片路径 # 设置图片的位置和大小 left = util.Cm(8.04) top = util.Cm(9.93) width = util.Cm(15.07) height = util.Cm(4.06) # 在页面中插入图片 slide.shapes.add_picture(img_path, left, top, width, height) if __name__ == "__main__": slide = ppt.slides[0] #第几页 rander_template(slide) insert_pic(slide) ppt.save('new.pptx') # 保存为文件
-
目录一、route()路由概述二、静态路由和动态路径方式1:静态路由方式2:动态路由三、route()其它参数1.methods=[‘GET’,‘POST’]一、route()路由概述功能:将URL绑定到函数路由函数route()的调用有两种方式:静态路由和动态路由二、静态路由和动态路径方式1:静态路由@app.route(“/xxx”) xxx为静态路径 如::/index / /base等,可以返回一个值、字符串、页面等12345678910111213from flask import Flaskapp = Flask(__name__) @app.route('/hello')def hello_world(): return 'Hello World!!!' @app.route('/pro')def index(): return render_template('login.html') if __name__ == '__main__': app.run(debug = True)方式2:动态路由采用<>进行动态url的传递@app.route(“/”),这里xxx为不确定的路径。123456789from flask import Flaskapp = Flask(__name__) @app.route('/hello/<name>')def hello_name(name): return 'Hello %s!' % name if __name__ == '__main__': app.run(debug = True)如果浏览器地址栏输入:http:// localhost:5000/hello/w3cschool则会在页面显示:Hello w3cschool!三、route()其它参数1.methods=[‘GET’,‘POST’]当前视图函数支持的请求方式,不设置默认为GET请求方式不区分大小写methods=[‘GET’] 支持的请求方法为GETmethods=[‘POST’] 支持的请求方法为POSTmethods=[‘GET’,‘POST’] 支持的请求方法为POST GET123456789101112@app.route('/login', methods=['GET', 'POST']) # 请求参数设置不区分大小写,源码中自动进行了upperdef login(): if request.method == 'GET': return render_template('login.html') elif request.method == 'POST': username = request.form.get('username') pwd = request.form.get('pwd') if username == 'yang' and pwd == '123456': session['username'] = username return 'login successed 200 ok!' else: return 'login failed!!!'
-
目录引言文本类型二进制类型使用 requests 把字符串按照文件上传引言你写了一个 api,接受 client 上传的文件,然后在上传到 oss,你会怎么做?先写硬盘,然后在上传到 oss?太笨了!你写了一个截图服务,截到的图要上传到 oss,你会怎么做?先写硬盘,在上传到 oss?太笨了!这篇文章教你重新做人!文本类型使用 io.StringIO1234567import iofrom loguru import loggerfile_like_obj = io.StringIO("hahaha")logger.debug(file_like_obj)logger.debug(type(file_like_obj))logger.debug(getattr(file_like_obj,'read'))logger.debug(file_like_obj.read())输出结果如下:2022-07-11 21:23:51.206 | DEBUG | __main__:<module>:8 - <_io.StringIO object at 0x100323eb0>2022-07-11 21:23:51.206 | DEBUG | __main__:<module>:9 - <class '_io.StringIO'>2022-07-11 21:23:51.206 | DEBUG | __main__:<module>:10 - <built-in method read of _io.StringIO object at 0x100323eb0>2022-07-11 21:23:51.206 | DEBUG | __main__:<module>:11 - hahaha再看一个熟悉的:12345import iofrom loguru import loggerfile_like_obj = io.StringIO("hahaha")with file_like_obj as f: logger.debug(f.read())输出结果如下:2022-07-11 21:35:04.620 | DEBUG | __main__:<module>:9 - hahaha二进制类型使用 io.BytesIO使用 requests 把字符串按照文件上传下面的代码是标准的上传文件的代码:123456import requestsimport ioresponse = requests.post('http://localhost:5000/', files={ 'file': open('纵观人类文明史.txt', 'r', encoding='utf-8')})print(response.text)但是我想把 open('纵观人类文明史.txt', 'r', encoding='utf-8') 替换为字符串。为此我想到的办法是把字符串先写到硬盘上,在按照上面的代码上传,可是这太低效率(硬盘太低效率),平白无故多了两次硬盘读写操作,我想直接把内存中的字符串按照文件上传有什么办法吗? 参考文档https://docs.python.org/zh-cn/3/library/io.html#io.StringIO
-
前言安装初始化项目结构三大命令前言本篇文章,阐述一下Flask中数据库的迁移为什么要说数据库迁移呢?比如我们以前有一个数据库,里面的信息有 id, name现在我想再加一个gender属性,应该怎么办呢?不可能直接把数据库删除掉吧。然后重新创建一个,因此本文介绍一种,通过数据库迁移的方法,可以保留原始的数据,并完成添加新的一列的方法。安装直接使用pip install flask-migrate即可初始化项目结构123# exts.pyfrom flask_sqlalchemy import SQLAlchemydb = SQLAlchemy()老样子,我们还是在exts.py中,初始我们的数据库,这里时放Flask扩展的地方。1234567# models.pyfrom exts import dbclass User(db.Model): id = db.Column(db.Integer,primary_key=True) username = db.Column(db.String(80),unique=True) def __repr__(self): return '<User %s>' % self.usernamemodels.py是放模型的地方。1234567891011# app.pyfrom flask import Flaskfrom exts import dbfrom flask_migrate import Migrateapp = Flask(__name__)app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:///foo.db"# !!!绑定app和数据库db.init_app(app)migrate = Migrate(app,db)if __name__ == '__main__': app.run()主程序,我们在!!!进行初始化数据库迁移的migrate 对象。初始化之后我们可以执行下面的三大命令去创建我们的数据库。就不需要db.create_all()命令啦。三大命令# (1)初始化flask db init# 把当前的模型添加到迁移文件flask db migrate# 将映射文件真正的映射到数据库中flask db upgrade(1)新建一个名字为migrations的文件夹,并且记录一个数据库版本号其他问题:如果报错[flask_migrate] Error: Can‘t locate revision identified by '409392ed6301'答:db revision --rev-id 409392ed6301 409392ed6301是问题的版本号Error: While importing ‘app’, an ImportError was raised.答:请先去运行一下app.py,确保app.py可以运行Error: Could not locate a Flask application. You did not provide the “FLASK_APP” environment variable, and a “wsgi.py” or “app.py” module was not found in the current directory. 答:请确保执行命令时的文件夹中有app.py文件
-
由于实际需要,简要写了个小脚本,并打包生成exe,供无网络环境下使用脚本1:显示当前时间与时间戳,以及10分钟后的时间与时间戳123456789# -*- coding: utf-8 -*- """Project: pyWorkspaceCreator: Administrator -haochuangCreate time: 2021-05-12 09:24IDE: PyCharmIntroduction: """12345678910111213141516171819202122232425262728293031323334353637import timeimport datetime t=datetime.datetime.now() #当前日期t1 =t.strftime('%Y-%m-%d %H:%M:%S')#转为秒级时间戳ts1=time.mktime(time.strptime(t1, '%Y-%m-%d %H:%M:%S'))#转为毫秒级end_time=int(str(ts1*1000).split(".")[0]) #10分钟后t2 = (t+datetime.timedelta(minutes=10)).strftime("%Y-%m-%d %H:%M:%S")# t2=(t-datetime.timedelta(hours=1)).strftime("%Y-%m-%d %H:%M:%S")#转为秒级时间戳ts2=time.mktime(time.strptime(t2, '%Y-%m-%d %H:%M:%S'))#转为毫秒级start_time=int(str(ts2*1000).split(".")[0]) #print("\n","*"*30)print("\n")print("*"*30)print("当前时间戳:")print(start_time)print("当前时间:")print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(ts2)))print("*"*30,"\n") print("10分钟后的时间戳:")print(end_time)print("10分钟后的时间:")print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(ts1))) print("*"*30,"\n")脚本2:显示当前时间与时间戳,以及10分钟后的时间与时间戳,允许根据输入的指定时间,生成多久之后的时间戳123456789# -*- coding: utf-8 -*- """Project: pyWorkspaceCreator: Administrator -haochuangCreate time: 2021-05-12 09:24IDE: PyCharmIntroduction: """1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950import timeimport datetime t=datetime.datetime.now() #当前日期t1 =t.strftime('%Y-%m-%d %H:%M:%S')#转为秒级时间戳ts1=time.mktime(time.strptime(t1, '%Y-%m-%d %H:%M:%S'))#转为毫秒级end_time=int(str(ts1*1000).split(".")[0]) #10分钟后t2 = (t+datetime.timedelta(minutes=10)).strftime("%Y-%m-%d %H:%M:%S")# t2=(t-datetime.timedelta(hours=1)).strftime("%Y-%m-%d %H:%M:%S")#转为秒级时间戳ts2=time.mktime(time.strptime(t2, '%Y-%m-%d %H:%M:%S'))#转为毫秒级start_time=int(str(ts2*1000).split(".")[0]) #print("\n","*"*30)print("\n")print("*"*30)print("当前时间戳:")print(start_time)print("当前时间:")print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(ts2)))print("*"*30,"\n") # 10分钟后的时间戳print("10 分钟后的时间戳:")print(end_time)print("10 分钟后的时间:")print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(ts1)))print("*"*30,"\n") # 用户自定义时间time_user = input("需要多少分钟后的时间戳(请输入正确int类型数值):")t3 = (t+datetime.timedelta(minutes=int(time_user))).strftime("%Y-%m-%d %H:%M:%S")ts3=time.mktime(time.strptime(t3, '%Y-%m-%d %H:%M:%S'))#转为毫秒级start_time=int(str(ts3*1000).split(".")[0]) print(time_user + " 分钟后的时间戳:")print(end_time)print(time_user + " 分钟后的时间:")print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(ts3)))print("*"*30,"\n")脚本3:显示部分时间与时间戳等1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556# -*- coding: utf-8 -*- """Project: pyWorkspaceCreator: Administrator -haochuangCreate time: 2021-05-12 09:24IDE: PyCharmIntroduction: """import timeimport datetimefrom datetime import timezonefrom datetime import timedelta # 显示当前秒级时间戳与毫秒级时间戳、微秒级时间戳t = time.time()#print(t) # 原始时间数据#print(int(t)) # 秒级时间戳#print(int(round(t * 1000))) # 毫秒级时间戳#print(int(round(t * 1000000))) # 微秒级时间戳 # 显示当前日期:dt = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')dt_ms = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f') # 含微秒的日期时间,来源 比特量化print("当前日期(s): " + dt)print("当前日期(ms): " + dt_ms) # 将日期转为秒级时间戳#dtt = '2018-01-01 10:40:30'#dtts = int(time.mktime(time.strptime(dt, "%Y-%m-%d %H:%M:%S")))#ts_ms = int(time.mktime(time.strptime(dt, "%Y-%m-%d %H:%M:%S")))t=datetime.datetime.now()print("当前时间戳(s): " + t)print("当前时间戳(ms): " + (int(round(t * 1000)))) # 国际标准时间print("国际标准时间: "+time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime()))# 本地时间print("本地当前时间: "+time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())) # 将当前日期转为秒级时间戳dt = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())dt_ts = int(time.mktime(time.strptime(dt, "%Y-%m-%d %H:%M:%S")))print("当前时间: " + dt)print("当前时间戳: " + dt_ts) # 将获取十分钟后的秒级时间戳#dt_10 = int((datetime.datetime.now()+datetime.timedelta(minutes=10)).strftime("%Y-%m-%d %H:%M:%S"))#ts_10 = int(time.mktime(time.strptime(dt_10, "%Y-%m-%d %H:%M:%S")))after10 = (datetime.datetime.now()+datetime.timedelta(minutes=10)).strftime("%Y-%m-%d %H:%M:%S")after10_ts = int(time.mktime(time.strptime(t1,after10)))print("10分钟后的时间: " + after10)print("10分钟后的时间戳: "脚本4:显示部分时间与时间戳等123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133# -*- coding: utf-8 -*- """Project: pyWorkspaceCreator: Administrator -haochuangCreate time: 2021-05-12 09:08IDE: PyCharmIntroduction: """ import datetimeimport time print('*'*30 +"获取时间方式")#获取当前时间:Thu Nov 03 16:40:00 2016print(time.strftime("%a %b %d %H:%M:%S %Y", time.localtime())) #获取当前时间:2016-11-03 16:40:00print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')) #获取年,月,日:2016-11-03print(datetime.date.today()) #获取当前时间:2016-11-03 16:43:14.550000print(datetime.datetime.now()) #不加参数是00:00,参数days=1表示一天:1 day, 0:00:00print(datetime.timedelta(days=1)) #获取昨天日期:2016-11-02nowtime=datetime.date.today()oldtime=datetime.timedelta(days=1)print(nowtime-oldtime) #获取昨天的精确日期oldtime=datetime.timedelta(days=1)print (datetime.datetime.now() - oldtime) print ('*'*30 + 'python时间处理之time模块') import time# 返回时间戳# print(time.time()) # 返回当前时间print(time.ctime()) # 返回一天前的时间print(time.ctime(time.time()-86400)) # 函数返回time.struct_time类型的对象time_obj = time.gmtime()print(time_obj)#结果:time.struct_time(tm_year=2016, tm_mon=7, tm_mday=27, tm_hour=8, tm_min=52, tm_sec=26, tm_wday=2, tm_yday=209, tm_isdst=0)# 格式化输出:print(time_obj.tm_year,time_obj.tm_mon,time_obj.tm_mday) print("{year}-{month}".format(year=time_obj.tm_year,month=time_obj.tm_mon)) # 以time.struct_time类型,打印本地时间print(time.localtime()) # 转换成时间戳time_obj = time.gmtime()print(time.mktime(time_obj)) # 延时2秒time.sleep(2) # 打印UTC,世界标准时间,北京时区是东八区,领先UTC八个小时print(time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime())) # 本地时间print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())) # 把time.struct_time类型时间,转换成时间戳tm = time.strptime("2016-05-6 15:06:33","%Y-%m-%d %H:%M:%S")print(tm)print(time.mktime(tm)) print ('*'*30 + '3-python时间处理之datetime模块') import datetime # 打印当前,年,月,日print(datetime.date.today()) # 打印当前时间,精确到微秒current_time = datetime.datetime.now()print(current_time) # 转成time.struct_time格式时间current_time = datetime.datetime.now()print(current_time.timetuple()) # 加十天print(datetime.datetime.now() +datetime.timedelta(days=10))# 减十天print(datetime.datetime.now() +datetime.timedelta(days=-10))# 减十个小时print(datetime.datetime.now() +datetime.timedelta(hours=-10))# 加120sprint(datetime.datetime.now() +datetime.timedelta(seconds=120)) # 替换成指定的时间cr_time = datetime.datetime.now()print(cr_time.replace(2014,9,12))# 结果:2014-09-12 17:28:17.522893 # 格式化输出print(datetime.datetime.strptime("21/11/06 16:30","%d/%m/%y %H:%M")) # 替换成指定时间后,类型是<class 'datetime.datetime'>current_time = datetime.datetime.now()time_obj = current_time.replace(2015,5)print(time_obj,type(time_obj))# 结果:2015-05-27 17:34:13.350245 <class 'datetime.datetime'> # 对比时间大小,取指定时间范围使用current_time = datetime.datetime.now()time_obj = current_time.replace(2015,5)print(current_time>time_obj) import datetimedef getYesterday(): today=datetime.date.today() oneday=datetime.timedelta(days=1) yesterday=today-oneday return yesterday # 输出print(getYesterday())脚本5:关于时间戳处理123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354# -*- coding: utf-8 -*- """Project: pyWorkspaceCreator: Administrator -haochuangCreate time: 2021-05-12 09:24IDE: PyCharmIntroduction: """import timeimport datetimefrom datetime import timezonefrom datetime import timedelta # 显示当前秒级时间戳与毫秒级时间戳、微秒级时间戳t = time.time()print(t) # 原始时间数据print(int(t)) # 秒级时间戳print(int(round(t * 1000))) # 毫秒级时间戳print(int(round(t * 1000000))) # 微秒级时间戳 # 显示当前日期:dt = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')dt_ms = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f') # 含微秒的日期时间,来源 比特量化print(dt)print(dt_ms) # 将日期转为秒级时间戳dt = '2018-01-01 10:40:30'ts = int(time.mktime(time.strptime(dt, "%Y-%m-%d %H:%M:%S")))print(ts) # 将秒级时间戳转为日期ts = 1515774430dt = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(ts))print(dt) # 时区转换# 显示UTC时间utc_now = datetime.datetime.utcnow()print(utc_now)# 世界标准时间# utc_time = datetime(2019, 7, 30, 7, 50, 0)print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))# 北京时间UTC+8# cst_time =utc_time.astimezone(timezone(timedelta(hours=-8))).strftime("%Y-%m-%d %H:%M:%S") # 国际标准时间print("国际标准时间:"+time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime()))# 本地时间print("本地时间:"+time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
-
目录目标效果设计开始步骤一步骤二步骤三步骤四步骤五今天我们来动手实现一款2048小游戏。这款游戏的精髓就玩家能够在于通过滑动屏幕合并相同数字,直到不能再合并为止。玩法可以说是非常的简单,但挑战性也是十足的。话不多说,让我们从0开始实现!目标效果大致要实现的效果如下:设计开始首先简单分析一下游戏的逻辑:输入移动方向,游戏内所有方块都朝指定方向移动同方向移动的方块,数字相同则合并,然后生成一个合并的方块合并后生成新的方块,无法生成新方块时游戏结束用一系列的颜色来区分不同分数的方块(可有可无,纯粹是为了美观)ok,游戏内再逻辑已经很清晰了。现在开始实现:步骤一新建一个文件夹用来放需要的游戏素材步骤二新建一个python程序,可以命名为2048,放在素材目录的同级文件夹下步骤三导入需要的依赖库:123import pygame as pyimport sys, random, time, redis, os,mathimport numpy as np依赖库中的redis是一个额外的数据库,用来存取游戏历史数据,需要的可以考虑安装,不需要的用excel表代替也可以。首先需要思考的是,游戏内的方块的移动本质上是坐标的变换,并且方块的坐标是固定的,也就是说,每次输入一个方向就按照一个移动函数将所有方块的坐标进行对应的转换。那么,如此以来,就需要建立一个坐标系用以标记方块的坐标。因为是4x4的游戏,那么就按照(1,1),(1,2),(1,3),...,(4,4)建立游戏坐标,然而相比直接移动坐标还是比较麻烦,一个简单的想法是,每个方块给一个唯一的标记,如我们需要实现4x4的游戏,就需要16个记号。而每一个标记就对应了唯一且固定的坐标。给出如下代码:123456789# 预加载移动逻辑def pre_move(): numberPos = {} for num in range(1, 17): row1, row2 = divmod(num, 4) row = row1 + np.sign(row2) column = [row2 if row2 != 0 else 4][0] numberPos['{}'.format([row, column])] = num return numberPos这里的numberPos实际上就是{‘{1,1}’:1,’{1,2}‘:2......}。当然如果想设计5x5或者6x6的只需要把循环里面的17和4改成25和5或36和6就行。ok,有了坐标接下来的问题好解决了。步骤四在新建的素材文件夹内放入一些图片方块(正方形)用来表示每个不同分数的方块。如下图所示:当然,不使用图片加载游戏也是可以的,如使用py.draw.rect()也能绘制图像,不过每次加载都绘制图像会占用游戏大量运算内存,并且使用图片可以自定义自己的游戏风格,修改上也非常便利。设置完成之后,定义一个游戏的初始化模块:12345678910111213141516171819# 主程序def game_start(): global screen, rate py.init() clock = py.time.Clock() screen_x = 500 # 请调到合适的大小 screen_y = math.ceil(screen_x * rate / rate2) screen = py.display.set_mode((screen_x, screen_y), depth=32) py.display.set_caption("终极2048") BackGround = [251, 248, 239] # 灰色 Icon = py.image.load('./素材/icon.png').convert_alpha() py.display.set_icon(Icon) screen.fill(color=BackGround) # 主界面下设计 width = math.floor(screen_x * rate) bgSecond = py.image.load('./素材/BG_02.png').convert_alpha() bgSecond = py.transform.smoothscale(bgSecond, (width, width)) bgSecondRect = bgSecond.get_rect() bgSecondRect.topleft = math.floor(screen_x * (1 - rate) / 2), math.floor(screen_y * (1 - rate2))游戏界面的大小请调节到合适的尺寸。接下来加载分数图片,以便游戏循环时随时可以调用。123456789101112131415161718192021222324252627282930313233343536373839404142# 预加载分数图def pre_load_image(background): imageList = {} imagePath = './素材/分数/' image_filenames = [i for i in os.listdir(imagePath)] width = math.floor(background.width * (1 - internalWidth) / 4) for name in image_filenames: image = py.transform.smoothscale(py.image.load(imagePath + name).convert_alpha(), (width, width)) imageList[name.replace('.png', '')] = image return imageList# 加载分数图像def draw_image(score_list, image_list, pos_list): for pos_num in score_list: score = score_list[pos_num] scoreSurf = BasicFont01.render('{}'.format(score), True, (0, 0, 0)) scoreRect = scoreSurf.get_rect() if score <= 4096: image = image_list['{}'.format(score)] else: image = image_list['4096'] imageRect = image.get_rect() imageRect.topleft = pos_list['{}'.format(pos_num)] scoreRect.center = imageRect.center screen.blit(image, imageRect) if score > 0: screen.blit(scoreSurf, scoreRect)# 图像位置列表,表示为(x,y)# 用于确定加载的分数图像的显示点位def image_pos_list(background): pre_x = background.topleft[0] pre_y = background.topleft[-1] internalLong = math.ceil(internalWidth / 5 * background.width) imageLong = math.floor((1 - internalWidth) / 4 * background.width) posList = dict(zip(list(range(1, 17)), [''] * 16)) for num in range(1, 17): row1, row2 = divmod(num, 4) row = row1 + np.sign(row2) column = [row2 if row2 != 0 else 4][0] image_x = pre_x + internalLong * column + imageLong * (column - 1) image_y = pre_y + internalLong * row + imageLong * (row - 1) posList['{}'.format(num)] = (image_x, image_y) return posList这里用了三个函数来加载游戏图片,分表表示:提取图片名保存到列表中,绘制游戏中的2,4,8等等数字在分数图片上。最后一个函数用于确定每个坐标在游戏界面的显示位置,并将其一一绑定。加载完成图像之后,就需要完成关键的移动逻辑,先上代码:12345678910111213141516171819202122232425262728293031323334353637383940414243# 移动逻辑def number_move(number_pos, move_input, score_list): values = list(number_pos.values()) keys = list(number_pos.keys()) numberPosReverse = dict(zip(values, keys)) newScoreList = score_list.copy() oldScoreList = {} while newScoreList != oldScoreList: oldScoreList = newScoreList.copy() for num in range(1, 17): pos = eval(numberPosReverse[num]) x, y = pos[0] + move_input[0], pos[1] + move_input[1] pos[0] = [x if 1 <= x <= 4 else pos[0]][0] pos[1] = [y if 1 <= y <= 4 else pos[1]][0] number = number_pos['{}'.format(pos)] oldNumberScore = newScoreList[num] nextNumberScore = newScoreList[number] syn = list(map(lambda x, y: abs(x) * abs(y), move_input, pos)) # 0值移动 if nextNumberScore == 0: newScoreList[number] = oldNumberScore newScoreList[num] = 0 # 无法移动 elif num == number: pass # 合并移动 elif oldNumberScore == nextNumberScore and num != number: newScoreList[number] = 2 * oldNumberScore newScoreList[num] = 0 # 边界移动 elif oldNumberScore != nextNumberScore and 1 in syn or 4 not in syn: pass # 非边界移动 elif oldNumberScore != nextNumberScore and 1 not in syn and 4 not in syn: x, y = pos[0] + move_input[0], pos[1] + move_input[1] next2NumberScore = newScoreList[number_pos['{}'.format([x, y])]] if next2NumberScore != nextNumberScore: pass elif next2NumberScore == nextNumberScore: newScoreList[number_pos['{}'.format([x, y])]] = 2 * next2NumberScore newScoreList[number] = oldNumberScore newScoreList[num] = 0 return newScoreList首先导入预先确定好的坐标,移动变量。根据前面分析的游戏逻辑,每次输入移动向量后游戏内的所有方块都需要移动,相同分数的方块需要一次性合并到一起,并且不能留空。详细分析一下就是:输入一个移动向量(x,y),如(+1,0)表示方块向右移动一格。对所有的原坐标进行计算并保留为移动后坐标,提取前后两次坐标对应的分数从1号标记开始循环判断:0值移动:如果移动后的分数为0,用旧坐标分数替代新坐标的分数,并删除旧坐标的分数无法移动:移动后的坐标与移动前的坐标相同,那么不做改变合并移动:新旧坐标对应的分数相同,那么新坐标分数x2,旧坐标分数删除边界移动:方块已经处于移动的边界,无法移动,不做修改非边界移动:新旧坐标对应的分数不同,且新坐标的下一个坐标对应的分数也不同,不做修改;新旧坐标对应的分数不同,且新坐标的下一个坐标对应的分数相同,修改循环整个逻辑,直到所有坐标对应的分数不再发生改变通过上述分析,移动逻辑函数实现了输入一个方向游戏内的分数动态发生变化。最后我们还需要一个游戏结束的函数:12345678910111213141516171819# 游戏结束def game_over(score,bg): ip = '127.0.0.1' password = None r = redis.Redis(host=ip, password=password, port=6379, db=2, decode_responses=True) r.hset('2048','{}'.format(time.localtime()),score) py.draw.rect(screen,bg,[0,0,screen.get_width(),screen.get_height()],0) BasicFont02 = py.font.SysFont('/素材/simkai.ttf', 40) overSurf = BasicFont01.render('Game Over', True, (0, 0, 0)) overRect = overSurf.get_rect() overRect.center = (math.floor(screen.get_width() / 2), math.floor(screen.get_height() / 2)) scoreSurf = BasicFont02.render('最终得分:', True, (0, 0, 0)) scoreRect = scoreSurf.get_rect() scoreRect.center = (math.floor(screen.get_width() / 2), math.floor(screen.get_height() * 0.6)) numberSurf = BasicFont02.render('{}'.format(score), True, (0, 0, 0)) numberRect = numberSurf.get_rect() numberRect.center = (math.floor(screen.get_width() / 2), math.floor(screen.get_height() * 0.7)) time.sleep(3) sys.exit()一个键盘控制代码,实现键盘控制游戏:123456789101112# 键盘控制函数def keyboard_ctrl(event): move_output = [0, 0] if event.key == py.K_UP: move_output = [-1, 0] elif event.key == py.K_DOWN: move_output = [1, 0] elif event.key == py.K_RIGHT: move_output = [0, 1] elif event.key == py.K_LEFT: move_output = [0, -1] return move_output一个新方块生成器,实现每次合并之后能在空白方块处随机生成2或4中的一个新分数,生成概率按照当前游戏中的2和4的数量为基础。123456789101112# 随机得分生成def random_score(score_list): values = list(score_list.values()) pro = [2] * (2 + values.count(2)) + [4] * (1 + values.count(4)) # 以当前分数图中2或4出现的频率为概率 blank = [[i if score_list[i] == 0 else 0][0] for i in range(1, 17)] blank = list(set(blank)) blank.remove(0) if not blank: return 'GameOver' # 游戏结束 else: score_list[random.choice(blank)] = random.choice(pro) return score_list一个得分统计器,每次游戏运行是统计当前得分和历史最高得分:123456789101112131415161718192021222324252627# 统计并记录当前得分def record_score(score_list, background): totalScore = 0 values = list(score_list.values()) for i in values: totalScore += i scoreSurf = BasicFont01.render('得分:{}'.format(totalScore), True, (0, 0, 0)) scoreRect = scoreSurf.get_rect() scoreRect.topleft = (math.floor(0.1 * screen.get_width()), math.floor(0.05 * screen.get_height())) scoreRect.width = math.floor((rate - 0.15) / 2 * screen.get_width()) scoreRect.height = math.floor((1 - rate2) / 3 * 2 * screen.get_height()) py.draw.rect(screen, background, [scoreRect.topleft[0], scoreRect.topleft[1], scoreRect.width, scoreRect.height], 0) screen.blit(scoreSurf, scoreRect) return totalScore# 绘制历史最高得分def draw_best(background): ip = '127.0.0.1' password = None r = redis.Redis(host=ip, password=password, port=6379, db=2, decode_responses=True) scores=[eval(i) for i in list(r.hgetall('2048').values())] best_scores=max(scores) scoreSurf=BasicFont01.render('最高得分:{}'.format(best_scores),True,(0,0,0)) scoreRect=scoreSurf.get_rect() scoreRect.width = math.floor((rate - 0.15) / 2 * screen.get_width()) scoreRect.height = math.floor((1 - rate2) / 3 * 2 * screen.get_height()) scoreRect.topright = (math.floor(0.9 * screen.get_width()), math.floor(0.05 * screen.get_height())) py.draw.rect(screen, background, [scoreRect.topleft[0], scoreRect.topleft[1], scoreRect.width, scoreRect.height], 0) screen.blit(scoreSurf, scoreRect)最后补充完整的游戏启动器:12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455# 主程序def game_start(): global screen, rate py.init() clock = py.time.Clock() screen_x = 500 # 请调到合适的大小 screen_y = math.ceil(screen_x * rate / rate2) screen = py.display.set_mode((screen_x, screen_y), depth=32) py.display.set_caption("终极2048") BackGround = [251, 248, 239] # 灰色 Icon = py.image.load('./素材/icon.png').convert_alpha() py.display.set_icon(Icon) screen.fill(color=BackGround) # 主界面下设计 width = math.floor(screen_x * rate) bgSecond = py.image.load('./素材/BG_02.png').convert_alpha() bgSecond = py.transform.smoothscale(bgSecond, (width, width)) bgSecondRect = bgSecond.get_rect() bgSecondRect.topleft = math.floor(screen_x * (1 - rate) / 2), math.floor(screen_y * (1 - rate2)) # 主界面上部分设计 # 预加载数据 draw_best(BackGround) posList = image_pos_list(bgSecondRect) imageList = pre_load_image(bgSecondRect) scoreList = dict(zip(list(range(1, 17)), [0] * 15 + [2])) # 分数表 numberPos = pre_move() scoreList = random_score(scoreList) totalScore=0 # 主循环 while True: screen.blit(bgSecond, bgSecondRect) # 刷新屏幕 if scoreList == 'GameOver': game_over(totalScore,BackGround) draw_image(scoreList, imageList, posList) # 绘制得分 totalScore = record_score(scoreList, BackGround) key = py.key.get_pressed() if key[py.K_ESCAPE]: exit() for event in py.event.get(): if event.type == py.QUIT: sys.exit() elif event.type == py.KEYDOWN: move_input = keyboard_ctrl(event) # 按下按键 scoreList = number_move(numberPos, move_input, scoreList) # 移动数字 scoreList = random_score(scoreList) # 在按下按键后生成新的数字 py.display.update() clock.tick(FPS)if __name__ == '__main__': py.font.init() BasicFont01 = py.font.Font('./素材/simkai.ttf', 30) screen = py.display.set_mode((500, 500)) rate = 0.95 # 游戏主界面下的宽度占整个游戏界面宽度的比例 rate2 = 0.7 # 游戏主界面下的高度占整个游戏界面高度的比例 internalWidth = 0.1 # 间隙比例 FPS = 50 # 游戏帧率 game_start()步骤五启动游戏运行之前别忘了启动redis服务器。运行效果图:(游戏界面设计的不够好。。。。,本来打算再加入一些小道具比如说:撤销,全屏合并等功能)
-
目录目标效果设计开始步骤一步骤二步骤三步骤四步骤五今天我们来动手实现一款2048小游戏。这款游戏的精髓就玩家能够在于通过滑动屏幕合并相同数字,直到不能再合并为止。玩法可以说是非常的简单,但挑战性也是十足的。话不多说,让我们从0开始实现!目标效果大致要实现的效果如下:设计开始首先简单分析一下游戏的逻辑:输入移动方向,游戏内所有方块都朝指定方向移动同方向移动的方块,数字相同则合并,然后生成一个合并的方块合并后生成新的方块,无法生成新方块时游戏结束用一系列的颜色来区分不同分数的方块(可有可无,纯粹是为了美观)ok,游戏内再逻辑已经很清晰了。现在开始实现:步骤一新建一个文件夹用来放需要的游戏素材步骤二新建一个python程序,可以命名为2048,放在素材目录的同级文件夹下步骤三导入需要的依赖库:123import pygame as pyimport sys, random, time, redis, os,mathimport numpy as np依赖库中的redis是一个额外的数据库,用来存取游戏历史数据,需要的可以考虑安装,不需要的用excel表代替也可以。首先需要思考的是,游戏内的方块的移动本质上是坐标的变换,并且方块的坐标是固定的,也就是说,每次输入一个方向就按照一个移动函数将所有方块的坐标进行对应的转换。那么,如此以来,就需要建立一个坐标系用以标记方块的坐标。因为是4x4的游戏,那么就按照(1,1),(1,2),(1,3),...,(4,4)建立游戏坐标,然而相比直接移动坐标还是比较麻烦,一个简单的想法是,每个方块给一个唯一的标记,如我们需要实现4x4的游戏,就需要16个记号。而每一个标记就对应了唯一且固定的坐标。给出如下代码:123456789# 预加载移动逻辑def pre_move(): numberPos = {} for num in range(1, 17): row1, row2 = divmod(num, 4) row = row1 + np.sign(row2) column = [row2 if row2 != 0 else 4][0] numberPos['{}'.format([row, column])] = num return numberPos这里的numberPos实际上就是{‘{1,1}’:1,’{1,2}‘:2......}。当然如果想设计5x5或者6x6的只需要把循环里面的17和4改成25和5或36和6就行。ok,有了坐标接下来的问题好解决了。步骤四在新建的素材文件夹内放入一些图片方块(正方形)用来表示每个不同分数的方块。如下图所示:当然,不使用图片加载游戏也是可以的,如使用py.draw.rect()也能绘制图像,不过每次加载都绘制图像会占用游戏大量运算内存,并且使用图片可以自定义自己的游戏风格,修改上也非常便利。设置完成之后,定义一个游戏的初始化模块:12345678910111213141516171819# 主程序def game_start(): global screen, rate py.init() clock = py.time.Clock() screen_x = 500 # 请调到合适的大小 screen_y = math.ceil(screen_x * rate / rate2) screen = py.display.set_mode((screen_x, screen_y), depth=32) py.display.set_caption("终极2048") BackGround = [251, 248, 239] # 灰色 Icon = py.image.load('./素材/icon.png').convert_alpha() py.display.set_icon(Icon) screen.fill(color=BackGround) # 主界面下设计 width = math.floor(screen_x * rate) bgSecond = py.image.load('./素材/BG_02.png').convert_alpha() bgSecond = py.transform.smoothscale(bgSecond, (width, width)) bgSecondRect = bgSecond.get_rect() bgSecondRect.topleft = math.floor(screen_x * (1 - rate) / 2), math.floor(screen_y * (1 - rate2))游戏界面的大小请调节到合适的尺寸。接下来加载分数图片,以便游戏循环时随时可以调用。123456789101112131415161718192021222324252627282930313233343536373839404142# 预加载分数图def pre_load_image(background): imageList = {} imagePath = './素材/分数/' image_filenames = [i for i in os.listdir(imagePath)] width = math.floor(background.width * (1 - internalWidth) / 4) for name in image_filenames: image = py.transform.smoothscale(py.image.load(imagePath + name).convert_alpha(), (width, width)) imageList[name.replace('.png', '')] = image return imageList# 加载分数图像def draw_image(score_list, image_list, pos_list): for pos_num in score_list: score = score_list[pos_num] scoreSurf = BasicFont01.render('{}'.format(score), True, (0, 0, 0)) scoreRect = scoreSurf.get_rect() if score <= 4096: image = image_list['{}'.format(score)] else: image = image_list['4096'] imageRect = image.get_rect() imageRect.topleft = pos_list['{}'.format(pos_num)] scoreRect.center = imageRect.center screen.blit(image, imageRect) if score > 0: screen.blit(scoreSurf, scoreRect)# 图像位置列表,表示为(x,y)# 用于确定加载的分数图像的显示点位def image_pos_list(background): pre_x = background.topleft[0] pre_y = background.topleft[-1] internalLong = math.ceil(internalWidth / 5 * background.width) imageLong = math.floor((1 - internalWidth) / 4 * background.width) posList = dict(zip(list(range(1, 17)), [''] * 16)) for num in range(1, 17): row1, row2 = divmod(num, 4) row = row1 + np.sign(row2) column = [row2 if row2 != 0 else 4][0] image_x = pre_x + internalLong * column + imageLong * (column - 1) image_y = pre_y + internalLong * row + imageLong * (row - 1) posList['{}'.format(num)] = (image_x, image_y) return posList这里用了三个函数来加载游戏图片,分表表示:提取图片名保存到列表中,绘制游戏中的2,4,8等等数字在分数图片上。最后一个函数用于确定每个坐标在游戏界面的显示位置,并将其一一绑定。加载完成图像之后,就需要完成关键的移动逻辑,先上代码:12345678910111213141516171819202122232425262728293031323334353637383940414243# 移动逻辑def number_move(number_pos, move_input, score_list): values = list(number_pos.values()) keys = list(number_pos.keys()) numberPosReverse = dict(zip(values, keys)) newScoreList = score_list.copy() oldScoreList = {} while newScoreList != oldScoreList: oldScoreList = newScoreList.copy() for num in range(1, 17): pos = eval(numberPosReverse[num]) x, y = pos[0] + move_input[0], pos[1] + move_input[1] pos[0] = [x if 1 <= x <= 4 else pos[0]][0] pos[1] = [y if 1 <= y <= 4 else pos[1]][0] number = number_pos['{}'.format(pos)] oldNumberScore = newScoreList[num] nextNumberScore = newScoreList[number] syn = list(map(lambda x, y: abs(x) * abs(y), move_input, pos)) # 0值移动 if nextNumberScore == 0: newScoreList[number] = oldNumberScore newScoreList[num] = 0 # 无法移动 elif num == number: pass # 合并移动 elif oldNumberScore == nextNumberScore and num != number: newScoreList[number] = 2 * oldNumberScore newScoreList[num] = 0 # 边界移动 elif oldNumberScore != nextNumberScore and 1 in syn or 4 not in syn: pass # 非边界移动 elif oldNumberScore != nextNumberScore and 1 not in syn and 4 not in syn: x, y = pos[0] + move_input[0], pos[1] + move_input[1] next2NumberScore = newScoreList[number_pos['{}'.format([x, y])]] if next2NumberScore != nextNumberScore: pass elif next2NumberScore == nextNumberScore: newScoreList[number_pos['{}'.format([x, y])]] = 2 * next2NumberScore newScoreList[number] = oldNumberScore newScoreList[num] = 0 return newScoreList首先导入预先确定好的坐标,移动变量。根据前面分析的游戏逻辑,每次输入移动向量后游戏内的所有方块都需要移动,相同分数的方块需要一次性合并到一起,并且不能留空。详细分析一下就是:输入一个移动向量(x,y),如(+1,0)表示方块向右移动一格。对所有的原坐标进行计算并保留为移动后坐标,提取前后两次坐标对应的分数从1号标记开始循环判断:0值移动:如果移动后的分数为0,用旧坐标分数替代新坐标的分数,并删除旧坐标的分数无法移动:移动后的坐标与移动前的坐标相同,那么不做改变合并移动:新旧坐标对应的分数相同,那么新坐标分数x2,旧坐标分数删除边界移动:方块已经处于移动的边界,无法移动,不做修改非边界移动:新旧坐标对应的分数不同,且新坐标的下一个坐标对应的分数也不同,不做修改;新旧坐标对应的分数不同,且新坐标的下一个坐标对应的分数相同,修改循环整个逻辑,直到所有坐标对应的分数不再发生改变通过上述分析,移动逻辑函数实现了输入一个方向游戏内的分数动态发生变化。最后我们还需要一个游戏结束的函数:12345678910111213141516171819# 游戏结束def game_over(score,bg): ip = '127.0.0.1' password = None r = redis.Redis(host=ip, password=password, port=6379, db=2, decode_responses=True) r.hset('2048','{}'.format(time.localtime()),score) py.draw.rect(screen,bg,[0,0,screen.get_width(),screen.get_height()],0) BasicFont02 = py.font.SysFont('/素材/simkai.ttf', 40) overSurf = BasicFont01.render('Game Over', True, (0, 0, 0)) overRect = overSurf.get_rect() overRect.center = (math.floor(screen.get_width() / 2), math.floor(screen.get_height() / 2)) scoreSurf = BasicFont02.render('最终得分:', True, (0, 0, 0)) scoreRect = scoreSurf.get_rect() scoreRect.center = (math.floor(screen.get_width() / 2), math.floor(screen.get_height() * 0.6)) numberSurf = BasicFont02.render('{}'.format(score), True, (0, 0, 0)) numberRect = numberSurf.get_rect() numberRect.center = (math.floor(screen.get_width() / 2), math.floor(screen.get_height() * 0.7)) time.sleep(3) sys.exit()一个键盘控制代码,实现键盘控制游戏:123456789101112# 键盘控制函数def keyboard_ctrl(event): move_output = [0, 0] if event.key == py.K_UP: move_output = [-1, 0] elif event.key == py.K_DOWN: move_output = [1, 0] elif event.key == py.K_RIGHT: move_output = [0, 1] elif event.key == py.K_LEFT: move_output = [0, -1] return move_output一个新方块生成器,实现每次合并之后能在空白方块处随机生成2或4中的一个新分数,生成概率按照当前游戏中的2和4的数量为基础。123456789101112# 随机得分生成def random_score(score_list): values = list(score_list.values()) pro = [2] * (2 + values.count(2)) + [4] * (1 + values.count(4)) # 以当前分数图中2或4出现的频率为概率 blank = [[i if score_list[i] == 0 else 0][0] for i in range(1, 17)] blank = list(set(blank)) blank.remove(0) if not blank: return 'GameOver' # 游戏结束 else: score_list[random.choice(blank)] = random.choice(pro) return score_list一个得分统计器,每次游戏运行是统计当前得分和历史最高得分:123456789101112131415161718192021222324252627# 统计并记录当前得分def record_score(score_list, background): totalScore = 0 values = list(score_list.values()) for i in values: totalScore += i scoreSurf = BasicFont01.render('得分:{}'.format(totalScore), True, (0, 0, 0)) scoreRect = scoreSurf.get_rect() scoreRect.topleft = (math.floor(0.1 * screen.get_width()), math.floor(0.05 * screen.get_height())) scoreRect.width = math.floor((rate - 0.15) / 2 * screen.get_width()) scoreRect.height = math.floor((1 - rate2) / 3 * 2 * screen.get_height()) py.draw.rect(screen, background, [scoreRect.topleft[0], scoreRect.topleft[1], scoreRect.width, scoreRect.height], 0) screen.blit(scoreSurf, scoreRect) return totalScore# 绘制历史最高得分def draw_best(background): ip = '127.0.0.1' password = None r = redis.Redis(host=ip, password=password, port=6379, db=2, decode_responses=True) scores=[eval(i) for i in list(r.hgetall('2048').values())] best_scores=max(scores) scoreSurf=BasicFont01.render('最高得分:{}'.format(best_scores),True,(0,0,0)) scoreRect=scoreSurf.get_rect() scoreRect.width = math.floor((rate - 0.15) / 2 * screen.get_width()) scoreRect.height = math.floor((1 - rate2) / 3 * 2 * screen.get_height()) scoreRect.topright = (math.floor(0.9 * screen.get_width()), math.floor(0.05 * screen.get_height())) py.draw.rect(screen, background, [scoreRect.topleft[0], scoreRect.topleft[1], scoreRect.width, scoreRect.height], 0) screen.blit(scoreSurf, scoreRect)最后补充完整的游戏启动器:12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455# 主程序def game_start(): global screen, rate py.init() clock = py.time.Clock() screen_x = 500 # 请调到合适的大小 screen_y = math.ceil(screen_x * rate / rate2) screen = py.display.set_mode((screen_x, screen_y), depth=32) py.display.set_caption("终极2048") BackGround = [251, 248, 239] # 灰色 Icon = py.image.load('./素材/icon.png').convert_alpha() py.display.set_icon(Icon) screen.fill(color=BackGround) # 主界面下设计 width = math.floor(screen_x * rate) bgSecond = py.image.load('./素材/BG_02.png').convert_alpha() bgSecond = py.transform.smoothscale(bgSecond, (width, width)) bgSecondRect = bgSecond.get_rect() bgSecondRect.topleft = math.floor(screen_x * (1 - rate) / 2), math.floor(screen_y * (1 - rate2)) # 主界面上部分设计 # 预加载数据 draw_best(BackGround) posList = image_pos_list(bgSecondRect) imageList = pre_load_image(bgSecondRect) scoreList = dict(zip(list(range(1, 17)), [0] * 15 + [2])) # 分数表 numberPos = pre_move() scoreList = random_score(scoreList) totalScore=0 # 主循环 while True: screen.blit(bgSecond, bgSecondRect) # 刷新屏幕 if scoreList == 'GameOver': game_over(totalScore,BackGround) draw_image(scoreList, imageList, posList) # 绘制得分 totalScore = record_score(scoreList, BackGround) key = py.key.get_pressed() if key[py.K_ESCAPE]: exit() for event in py.event.get(): if event.type == py.QUIT: sys.exit() elif event.type == py.KEYDOWN: move_input = keyboard_ctrl(event) # 按下按键 scoreList = number_move(numberPos, move_input, scoreList) # 移动数字 scoreList = random_score(scoreList) # 在按下按键后生成新的数字 py.display.update() clock.tick(FPS)if __name__ == '__main__': py.font.init() BasicFont01 = py.font.Font('./素材/simkai.ttf', 30) screen = py.display.set_mode((500, 500)) rate = 0.95 # 游戏主界面下的宽度占整个游戏界面宽度的比例 rate2 = 0.7 # 游戏主界面下的高度占整个游戏界面高度的比例 internalWidth = 0.1 # 间隙比例 FPS = 50 # 游戏帧率 game_start()步骤五启动游戏运行之前别忘了启动redis服务器。运行效果图:(游戏界面设计的不够好。。。。,本来打算再加入一些小道具比如说:撤销,全屏合并等功能)
-
目录前言安装创建虚拟环境进入虚拟环境安装 flaskCookie的使用Session的使用前言本篇文章,阐述一下Flask中Cookie和Session为什么要说Cookie和Session呢?答:因为http请求是无状态的,怎么理解呢?当你访问B站时,如果你没有Cookie或者Session,B站就认为你是一个没有登录的用户。如果你有Cookie或Session,那么B站就知道你登录了,并且知道你是谁。所以可以把跟你相关的资料返回给你两者的区别:答:Cookie是明文,Session是加密的Cookie。安装创建虚拟环境123mkdir myprojectcd myprojectpython3 -m venv venv进入虚拟环境1. venv/bin/activate安装 flask1pip install FlaskCookie的使用12345678910111213141516from flask import Flask, Response, requestapp = Flask(__name__)@app.route("/set_cookie")def set_cookie(): response = Response("set cookie success") response.set_cookie("user_id","123") return response@app.route("/get_cookie")def get_cookie(): cookies = request.cookies if cookies.get("user_id") == "123": return "尊敬的用户你好,你的cookies是" + str(cookies) else: return "你不是VIP,请先获取身份"if __name__ == "__main__": app.run(debug=True,port=5000)第一次首先访问/home地址,会发现你没有Cookie给你返回一个你不是VIP,请先获取身份但是当我们首先访问/set_cookie,我们就会获得一个cookie,然后我们在访问/home地址,就可以成功的显示尊敬的用户您好了Session的使用12345678910111213141516from flask import Flask, sessionapp = Flask(__name__)# !!!你需要设置一个SECRET_KEY用来加密Cookieapp.config["SECRET_KEY"] = "123"@app.route("/set_session")def set_session(): session["user_name"] = "zhuxiaoxiao" return "设置session成功" + session["user_name"]@app.route("/home")def home(): if session.get("user_name") == "zhuxiaoxiao": return "尊敬的用户,登录成功" else: return "请先登录好吗?"if __name__ == "__main__": app.run(debug=True,port=5000)Session的使用方式整体和Cookie是一样的。需要注意的是使用Session前,必须要进行设置SECRET_KEY,用来加密Cookie
-
目录1. 安装yaml库2. yaml转json3. json转yaml4. 批量将yaml与json文件互相转换1. 安装yaml库想要使用python实现yaml与json格式互相转换,需要先下载pip,再通过pip安装yaml库。如何下载以及使用pip,可参考:pip的安装与使用,解决pip下载速度慢的问题安装yaml库:1pip install pyyaml2. yaml转json新建一个test.yaml文件,添加以下内容:123456789A: hello: name: Michael address: Beijing B: hello: name: jack address: Shanghai代码如下:1234567891011121314import yamlimport json # yaml文件内容转换成json格式def yaml_to_json(yamlPath): with open(yamlPath, encoding="utf-8") as f: datas = yaml.load(f,Loader=yaml.FullLoader) # 将文件的内容转换为字典形式 jsonDatas = json.dumps(datas, indent=5) # 将字典的内容转换为json格式的字符串 print(jsonDatas) if __name__ == "__main__": jsonPath = 'E:/Code/Python/test/test.yaml' yaml_to_json(jsonPath) 执行结果如下:{ "A": { "hello": { "name": "Michael", "address": "Beijing" } }, "B": { "hello": { "name": "jack", "address": "Shanghai" } }}3. json转yaml新建一个test.json文件,添加以下内容:1234567891011121314{ "A": { "hello": { "name": "Michael", "address": "Beijing" } }, "B": { "hello": { "name": "jack", "address": "Shanghai" } }}代码如下:12345678910111213import yamlimport json # json文件内容转换成yaml格式def json_to_yaml(jsonPath): with open(jsonPath, encoding="utf-8") as f: datas = json.load(f) # 将文件的内容转换为字典形式 yamlDatas = yaml.dump(datas, indent=5, sort_keys=False) # 将字典的内容转换为yaml格式的字符串 print(yamlDatas) if __name__ == "__main__": jsonPath = 'E:/Code/Python/test/test.json' json_to_yaml(jsonPath)执行结果如下:A: hello: name: Michael address: BeijingB: hello: name: jack address: Shanghai注意,如果不加sort_keys=False,那么默认是排序的,则执行结果如下:A: hello: address: Beijing name: MichaelB: hello: address: Shanghai name: jack4. 批量将yaml与json文件互相转换yaml与json文件互相转换:123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132import yamlimport jsonimport osfrom pathlib import Pathfrom fnmatch import fnmatchcase class Yaml_Interconversion_Json: def __init__(self): self.filePathList = [] # yaml文件内容转换成json格式 def yaml_to_json(self, yamlPath): with open(yamlPath, encoding="utf-8") as f: datas = yaml.load(f,Loader=yaml.FullLoader) jsonDatas = json.dumps(datas, indent=5) # print(jsonDatas) return jsonDatas # json文件内容转换成yaml格式 def json_to_yaml(self, jsonPath): with open(jsonPath, encoding="utf-8") as f: datas = json.load(f) yamlDatas = yaml.dump(datas, indent=5) # print(yamlDatas) return yamlDatas # 生成文件 def generate_file(self, filePath, datas): if os.path.exists(filePath): os.remove(filePath) with open(filePath,'w') as f: f.write(datas) # 清空列表 def clear_list(self): self.filePathList.clear() # 修改文件后缀 def modify_file_suffix(self, filePath, suffix): dirPath = os.path.dirname(filePath) fileName = Path(filePath).stem + suffix newPath = dirPath + '/' + fileName # print('{}_path:{}'.format(suffix, newPath)) return newPath # 原yaml文件同级目录下,生成json文件 def generate_json_file(self, yamlPath, suffix ='.json'): jsonDatas = self.yaml_to_json(yamlPath) jsonPath = self.modify_file_suffix(yamlPath, suffix) # print('jsonPath:{}'.format(jsonPath)) self.generate_file(jsonPath, jsonDatas) # 原json文件同级目录下,生成yaml文件 def generate_yaml_file(self, jsonPath, suffix ='.yaml'): yamlDatas = self.json_to_yaml(jsonPath) yamlPath = self.modify_file_suffix(jsonPath, suffix) # print('yamlPath:{}'.format(yamlPath)) self.generate_file(yamlPath, yamlDatas) # 查找指定文件夹下所有相同名称的文件 def search_file(self, dirPath, fileName): dirs = os.listdir(dirPath) for currentFile in dirs: absPath = dirPath + '/' + currentFile if os.path.isdir(absPath): self.search_file(absPath, fileName) elif currentFile == fileName: self.filePathList.append(absPath) # 查找指定文件夹下所有相同后缀名的文件 def search_file_suffix(self, dirPath, suffix): dirs = os.listdir(dirPath) for currentFile in dirs: absPath = dirPath + '/' + currentFile if os.path.isdir(absPath): if fnmatchcase(currentFile,'.*'): pass else: self.search_file_suffix(absPath, suffix) elif currentFile.split('.')[-1] == suffix: self.filePathList.append(absPath) # 批量删除指定文件夹下所有相同名称的文件 def batch_remove_file(self, dirPath, fileName): self.search_file(dirPath, fileName) print('The following files are deleted:{}'.format(self.filePathList)) for filePath in self.filePathList: if os.path.exists(filePath): os.remove(filePath) self.clear_list() # 批量删除指定文件夹下所有相同后缀名的文件 def batch_remove_file_suffix(self, dirPath, suffix): self.search_file_suffix(dirPath, suffix) print('The following files are deleted:{}'.format(self.filePathList)) for filePath in self.filePathList: if os.path.exists(filePath): os.remove(filePath) self.clear_list() # 批量将目录下的yaml文件转换成json文件 def batch_yaml_to_json(self, dirPath): self.search_file_suffix(dirPath, 'yaml') print('The converted yaml file is as follows:{}'.format(self.filePathList)) for yamPath in self.filePathList: try: self.generate_json_file(yamPath) except Exception as e: print('YAML parsing error:{}'.format(e)) self.clear_list() # 批量将目录下的json文件转换成yaml文件 def batch_json_to_yaml(self, dirPath): self.search_file_suffix(dirPath, 'json') print('The converted json file is as follows:{}'.format(self.filePathList)) for jsonPath in self.filePathList: try: self.generate_yaml_file(jsonPath) except Exception as e: print('JSON parsing error:{}'.format(jsonPath)) print(e) self.clear_list() if __name__ == "__main__": dirPath = 'C:/Users/hwx1109527/Desktop/yaml_to_json' fileName = 'os_deploy_config.yaml' suffix = 'yaml' filePath = dirPath + '/' + fileName yaml_interconversion_json = Yaml_Interconversion_Json() yaml_interconversion_json.batch_yaml_to_json(dirPath) # yaml_interconversion_json.batch_json_to_yaml(dirPath) # yaml_interconversion_json.batch_remove_file_suffix(dirPath, suffix)
-
任务:计算猴子吃桃问题。猴子第 1 天摘了若干个桃子,当即吃了一半零一个;第 2 剩下的吃了一半零一个,一次循环。到第十天时想吃就剩下一个桃子。求第一天摘了几个桃子?本小白的代码是:j = 1for i in range(1,10): j = (j+1)*2print(j)输出结果为:1534 本小白的思路是:属于数学的递归问题,在高中一个用数列的方式解决(也许)。但是,在Python中,可以利用for in range进行循环。D9=X/2-1=D10,因此推导出,D9=2*(D10+1),即f{x+1}=2[f(x)+1]所以,j = (j+1)*2。写在最后,作者本科商科,从未碰过代码。因,研究生专业为区块链技术,不得已开始自学编程。以上帖子仅为作者对该任务的一些粗浅认识,如果其中文字或者代码有误,希望各位大神/大佬/前辈不吝赐教,谢谢!!!
-
任务:当前有一组成绩单: score = [100,79,65,87,97,65,87,97,67] 请去除成绩单中成绩大于 80 的成绩,并将取出后的列表打印出来 本小白的代码是:score = [100,79,65,87,97,65,87,97,67]for i in score: if i > 80: continue print(i,end=" ")输出结果为:79 65 65 67 本小白的思路是:首先,确定给定数据——列表,因此可以直接使用,如果是其他的话需要转换。eg.score = 100,79,65,87,97,65,87,97,67score_list=list(score)接着,取出小于80的值。在这里的思路为,利用for和if函数遍历列表的数字,并在数值大于80时continue(跳过)。利用for和if函数遍历列表中的数字:score = [100,79,65,87,97,65,87,97,67]for i in score:#遍历数字 if i > 80: continue#当列表中的数字大于80时跳过 print(i,end=" ")#打印数字,并使用end让数字间空格为1.更多的思考在部分操作中,可能还需要将学生成绩排序。因此,可以在代码中增加相关语句以实现该目的。将获得列表中的数值从大到小排序:raw_score = score.copy() # copy 方法实现浅拷贝raw_score.sort(reverse=True)※Python对部分字符大小写有要求,不用把True写成true。※※排序后原数据会被更改,因此在此操作前一定要copy!!全部代码为:score = [100,79,65,87,97,65,87,97,67]for i in score: if i > 80: continue print(i,end=" ")print()sort_score = score.copy() sort_score.sort(reverse=True)for i in sort_score: if i > 80: continue print(i,end=" ")print()print(score)print(sort_score)输出结果为:79 65 65 67 #未排序,符合小于8079 67 65 65 #排序,符合小于80[100, 79, 65, 87, 97, 65, 87, 97, 67]#未排序,原数据[100, 97, 97, 87, 87, 79, 67, 65, 65]#排序,从大到小数据写在最后,作者本科商科,从未碰过代码。因,研究生专业为区块链技术,不得已开始自学编程。以上帖子仅为作者对该任务的一些粗浅认识,如果其中文字或者代码有误,希望各位大神/大佬/前辈不吝赐教,谢谢!!!
-
【功能模块】电磁计算平台MindElec【操作步骤&问题现象】需求:在RTX3060 Gpu上运行mindelec电磁计算平台,由于官方只支持ascend,只能用源码编译的方式1、在wsl中完成minds pore1.7-gpu版本的安装及测试后,尝试在Ubuntu-20.04的wsl中利用源码编译的方式安装mindelec敲出命令 bash build.sh -e gpu 出现报错-- Could NOT find Python3 (missing: Python3_INCLUDE_DIRS Development) (found version "3.8.10")CMake Error at CMakeLists.txt:35 (find_python_package): Unknown CMake command "find_python_package".-- Configuring incomplete, errors occurred!See also "/home/lihongji/mindscience/MindElec/build/mindelec/CMakeFiles/CMakeOutput.log".2、详细操作信息:(base) lihongji@LAPTOP-P7NAUT00:~/mindscience/MindElec$ bash build.sh -e gpumkdir: created directory '/home/lihongji/mindscience/MindElec/output'---------------- MindElec: build start ----------------start build mindelec project.-DDEBUG_MODE=off -DBUILD_PATH=/home/lihongji/mindscience/MindElec/build/ -DENABLE_GPU=ONMD LIBS CACHE PATH: /home/lihongji/mindscience/MindElec/build/mindelec/.mdlibset make thread num: 8pkg name:pybind11,pybind11pybind11 config hash: 5253018179879c380bb2d33c476f2438-- Found pybind11: /home/lihongji/mindscience/MindElec/build/mindelec/.mdlib/pybind11_5253018179879c380bb2d33c476f2438/include (found version "2.6.1" )Found pkg: pybind11pkg name:glog,glogglog config hash: 6f581a3db68ffe9e125bd4c496da9aaa_FIND:/home/lihongji/mindscience/MindElec/build/mindelec/.mdlib/glog_6f581a3db68ffe9e125bd4c496da9aaafound /home/lihongji/mindscience/MindElec/build/mindelec/.mdlib/glog_6f581a3db68ffe9e125bd4c496da9aaa/lib/libglog.soFound libs: glog::glogpkg name:nlohmann_json,nlohmann_jsonnlohmann_json config hash: e0a3765b49b7f4747a26bc3db79d0028========== External libs built successfully ==========-- Could NOT find Python3 (missing: Python3_INCLUDE_DIRS Development) (found version "3.8.10")CMake Error at CMakeLists.txt:35 (find_python_package): Unknown CMake command "find_python_package".-- Configuring incomplete, errors occurred!See also "/home/lihongji/mindscience/MindElec/build/mindelec/CMakeFiles/CMakeOutput.log".之前已经完成过一部分的编译,重新编译只显示该部分信息【截图信息】【日志信息】(可选,上传日志内容或者附件)
-
方法一:离线包安装方式(推荐)到VS Code插件官网vscode_marketplace搜索待安装的Python插件,Python插件路径。单击进入Python插件的Version History页签后,下载该插件的离线安装包,如图所示。图1 Python插件离线安装包在本地VS Code环境中,将下载好的.vsix文件拖动到远端Notebook中。右键点击该文件,选择Install Extension VSIX。方法二:设置远端默认安装的插件按照VS Code中设置远端默认安装的插件配置,即会在连接远端时自动安装,减少等待时间。方法三:VS Code官网排查方式https://code.visualstudio.com/docs/remote/troubleshooting小技巧(按需调整远端连接的相关参数): "remote.SSH.connectTimeout": 10, "remote.SSH.maxReconnectionAttempts": null, "remote.downloadExtensionsLocally": true, "remote.SSH.useLocalServer": false, "remote.SSH.localServerDownload": "always",
推荐直播
-
HDC深度解读系列 - Serverless与MCP融合创新,构建AI应用全新智能中枢2025/08/20 周三 16:30-18:00
张昆鹏 HCDG北京核心组代表
HDC2025期间,华为云展示了Serverless与MCP融合创新的解决方案,本期访谈直播,由华为云开发者专家(HCDE)兼华为云开发者社区组织HCDG北京核心组代表张鹏先生主持,华为云PaaS服务产品部 Serverless总监Ewen为大家深度解读华为云Serverless与MCP如何融合构建AI应用全新智能中枢
回顾中 -
关于RISC-V生态发展的思考2025/09/02 周二 17:00-18:00
中国科学院计算技术研究所副所长包云岗教授
中科院包云岗老师将在本次直播中,探讨处理器生态的关键要素及其联系,分享过去几年推动RISC-V生态建设实践过程中的经验与教训。
回顾中 -
一键搞定华为云万级资源,3步轻松管理企业成本2025/09/09 周二 15:00-16:00
阿言 华为云交易产品经理
本直播重点介绍如何一键续费万级资源,3步轻松管理成本,帮助提升日常管理效率!
回顾中
热门标签