diff --git a/.gitignore b/.gitignore index 9be43b8..ab59a67 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ *.csv .* +venv/ test/ data/ build/ diff --git a/Docker/Dockerfile b/Docker/Dockerfile deleted file mode 100644 index 3b00e15..0000000 --- a/Docker/Dockerfile +++ /dev/null @@ -1,66 +0,0 @@ -# Dockerfile by xianhu: build a docker image -# centos6: -# docker build -t user/centos6:v6.9.4 . -# docker run -it --name test [-p -v] user/centos6 -# docker attach test -# centos7: -# docker build -t user/centos7:v6.9.4 . -# docker run -dt --privileged --name test [-p -v] user/centos7 -# docker exec -it test /bin/bash - -FROM centos:6.9 -MAINTAINER xianhu - -# change system environments -ENV LANG en_US.UTF-8 -ENV LC_ALL en_US.UTF-8 - -# change system local time -RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime - -# fix: warning: rpmts_HdrFromFdno -RUN rpm --import /etc/pki/rpm-gpg/RPM* - -# update yum and install something -RUN yum update -y -RUN yum install -y xz -RUN yum install -y vim -RUN yum install -y git -RUN yum install -y gcc -RUN yum install -y make -RUN yum install -y wget -RUN yum install -y screen -RUN yum install -y gcc-c++ -RUN yum install -y crontabs -RUN yum install -y zlib-devel -RUN yum install -y sqlite-devel -RUN yum install -y openssl-devel - -# install python -RUN yum install -y https://centos6.iuscommunity.org/ius-release.rpm -# RUN yum install -y https://centos7.iuscommunity.org/ius-release.rpm -RUN yum install -y python36u -RUN yum install -y python36u-pip -RUN yum install -y python36u-devel - -# install nginx -RUN yum install -y epel-release -RUN yum install -y nginx - -# clean yum cache -RUN yum clean all - -# install libs of python3 -ADD ./requirements.txt /root/ -WORKDIR /root/ -RUN pip3.6 install --upgrade pip -RUN pip3.6 install -r requirements.txt - -# clean everything -RUN rm -rf /root/* - -# centos6 -CMD /bin/bash - -# centos7 -# ENTRYPOINT /usr/sbin/init diff --git a/Docker/requirements.txt b/Docker/requirements.txt deleted file mode 100644 index 9333583..0000000 --- a/Docker/requirements.txt +++ /dev/null @@ -1,39 +0,0 @@ -virtualenv -pylint -lxml -html5lib -xmltodict -pybloom_live -fake-useragent -beautifulsoup4 -aiohttp -requests -websocket-client -redis -PyMySQL -elasticsearch -Flask -Flask-WTF -Flask-Mail -Flask-Login -Flask-Moment -Flask-Script -Flask-RESTful -Flask-Migrate -Flask-HTTPAuth -Flask-Bootstrap -Flask-SQLAlchemy -dash -dash-table -dash-core-components -dash-html-components -dash-bootstrap-components -gunicorn -uWSGI -numpy -scipy -pandas -scikit-learn -matplotlib -plotly -jupyter diff --git a/README.md b/README.md index ce18449..812e234 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,18 @@ ### python_numpy.py: 使用numpy进行矩阵操作 +### python_mail.py: 使用Python自动发送邮件,包括发送HTML以及图片、附件等 + +### python_redis.py: Python操作Redis实现消息的发布与订阅 + +### python_schedule.py: Python进行调度开发 + +### python_socket.py: Python的socket开发实例 + +### python_re.py:Python的re模块的主要功能以及如何使用它们进行字符串匹配和替换 + ### Plotly目录: 一些plotly画图的实例,使用jupyter notebook编写 + =================================================================================================== ### 您可以fork该项目, 并在修改后提交Pull request, 看到后会尽量进行代码合并 diff --git a/python_celery.py b/python_celery.py new file mode 100644 index 0000000..f7c8f9a --- /dev/null +++ b/python_celery.py @@ -0,0 +1,23 @@ +# _*_ coding: utf-8 _*_ + +""" +测试celery +终端运行:celery -A python_celery:app worker -l INFO +""" + +import time + +from celery import Celery + +broker = "redis://localhost:6379/10" # 用redis做broker,中间件 +backend = "redis://localhost:6379/11" # 用redis做broken,用来保存结果 + +app = Celery("tasks", broker=broker, backend=backend) + + +@app.task +def add(x, y): + print(time.time(), x, y) + time.sleep(3) + print(time.time(), x, y, "--") + return x + y diff --git a/python_celery_test.py b/python_celery_test.py new file mode 100644 index 0000000..f3d1dbc --- /dev/null +++ b/python_celery_test.py @@ -0,0 +1,18 @@ +# _*_ coding: utf-8 _*_ + +""" +测试 +""" + +import time + +from python_celery import add + +if __name__ == "__main__": + result = [] + for i in range(10): + result.append(add.delay(i, i)) + print("----", time.time()) + for index, item in enumerate(result): + print(index, item.get()) + print("----", time.time()) diff --git a/python_mail.py b/python_mail.py new file mode 100644 index 0000000..a57049a --- /dev/null +++ b/python_mail.py @@ -0,0 +1,71 @@ +# _*_ coding: utf-8 _*_ + +""" +python发送邮件 +""" + +import smtplib +from email.header import Header +from email.mime.text import MIMEText +from email.mime.image import MIMEImage +from email.mime.multipart import MIMEMultipart + +# 第三方 SMTP 服务(以腾讯企业邮件和QQ邮箱为例) +mail_host = "smtp.exmail.qq.com" +# mail_host = "smtp.qq.com" +mail_user = "from@from.com.cn" +# mail_user = "from@qq.com" +mail_pass = "授权码" +mail_sender = mail_user +mail_port = 465 +mail_receivers = ["to@to.com", "to@qq.com"] + +# 设置邮件格式、内容等 -- 普通格式 ================================================ +message = MIMEText("邮件内容", "plain", "utf-8") + +# 设置邮件格式、内容等 -- HTML格式 =============================================== +msg_html = """ +

Python 邮件发送测试...

+

这是一个链接

+ + + + +
MonthSavings
January$100
February$80
+""" +message = MIMEText(msg_html, "html", "utf-8") + +# 设置邮件格式、内容等 -- HTML格式(带有图片和附件)================================== +msg_html = """ +

Python 邮件发送测试...

+

这是一个链接

+

图片演示:

+

+""" +msg_content = MIMEText(msg_html, "html", "utf-8") +msg_image = MIMEImage(open("test.png", "rb").read()) +msg_image.add_header("Content-ID", "") + +msg_file = MIMEText(open("test.csv", "rb").read(), "base64", "utf-8") +msg_file["Content-Type"] = "application/octet-stream" +msg_file["Content-Disposition"] = "attachment; filename=\"test.csv\"" + +message = MIMEMultipart("related") +message.attach(msg_content) +message.attach(msg_image) +message.attach(msg_file) +# ============================================================================== + +# 设置邮件的收发件、标题等 +message["From"] = mail_sender +message["To"] = ";".join(mail_receivers) +message["Subject"] = Header("邮件标题", "utf-8") + +try: + # 登录,并发送邮件 + smtpObj = smtplib.SMTP_SSL(mail_host, mail_port) + smtpObj.login(mail_user, mail_pass) + smtpObj.sendmail(mail_sender, mail_receivers, message.as_string()) + print("success") +except smtplib.SMTPException as excep: + print("error", excep) diff --git a/python_re.py b/python_re.py new file mode 100644 index 0000000..4e548f6 --- /dev/null +++ b/python_re.py @@ -0,0 +1,83 @@ +import re + +#-- 基本正则表达式语法 +''' +.:匹配除换行符以外的任意字符。 +^:匹配字符串的开始。 +$:匹配字符串的结束。 +*:匹配前一个字符0次或多次。 ++:匹配前一个字符1次或多次。 +?:匹配前一个字符0次或1次。 +{m}:匹配前一个字符m次。 +{m,n}:匹配前一个字符至少m次,至多n次。 +[abc]:匹配字符集合中的任意一个字符(例如a、b或c)。 +[^abc]:匹配不在字符集合中的任意字符。 +|:表示“或”关系,匹配符号前后的任意一个表达式。 +():用于分组,可以提取匹配的部分。 +\d:匹配任意数字,等价于[0-9]。 +\D:匹配任意非数字字符,等价于[^0-9]。 +\w:匹配任意字母数字字符,包括下划线,等价于[a-zA-Z0-9_]。 +\W:匹配任意非字母数字字符,等价于[^a-zA-Z0-9_]。 +\s:匹配任意空白字符,包括空格、制表符、换行符等。 +\S:匹配任意非空白字符。 +''' + +#-- re 模块的主要函数 +re.match(pattern, string, flags=0) # 尝试从字符串的起始位置匹配正则表达式,如果匹配成功,返回一个匹配对象;否则返回None。 +re.search(pattern, string, flags=0) # 扫描整个字符串,返回第一个成功匹配的对象;否则返回None。 +re.findall(pattern, string, flags=0) # 在字符串中找到所有与正则表达式匹配的非重叠匹配项,并返回一个列表。 +re.finditer(pattern, string, flags=0) # 与findall类似,但返回的是一个迭代器,每个迭代元素都是一个匹配对象。 +re.sub(pattern, repl, string, count=0, flags=0) # 使用repl替换string中所有与pattern匹配的子串,count表示替换的最大次数。 +re.subn(pattern, repl, string, count=0, flags=0) # 功能与sub相同,但返回一个元组,包含替换后的字符串和替换的总次数。 +re.split(pattern, string, maxsplit=0, flags=0) # 根据正则表达式的模式分割字符串,maxsplit表示分割的最大次数。 +re.escape(string) # 对字符串中的非字母数字字符进行转义,使其可以安全地用于正则表达式中。 + +#-- 示例代码1 +# 匹配字符串的开始 +match_obj = re.match(r'^Hello', 'Hello World') +if match_obj: + print("Match found:", match_obj.group()) +else: + print("No match") + +# 搜索字符串 +search_obj = re.search(r'World', 'Hello World') +if search_obj: + print("Search found:", search_obj.group()) +else: + print("No search match") + +# 查找所有匹配项 +findall_result = re.findall(r'\d+', 'There are 42 apples and 33 oranges') +print("Findall result:", findall_result) + +# 替换匹配项 +sub_result = re.sub(r'\d+', 'many', 'There are 42 apples and 33 oranges') +print("Sub result:", sub_result) + +# 分割字符串 +split_result = re.split(r'\s+', 'Hello World this is Python') +print("Split result:", split_result) + +# 转义字符串 +escaped_string = re.escape('Hello? World!') +print("Escaped string:", escaped_string) + +#-- 标志位(flags) +re.IGNORECASE # 忽略大小写。 +re.MULTILINE # 多行模式,改变^和$的行为。 +re.DOTALL # 让.匹配包括换行符在内的所有字符。 +re.VERBOSE # 允许正则表达式包含空白和注释,使其更易于阅读。 + +#-- 示例代码2 +pattern = re.compile(r''' + \d+ # 匹配一个或多个数字 + \. # 匹配小数点 + \d+ # 匹配一个或多个数字 +''', re.VERBOSE) + +match_obj = pattern.match('123.456') +if match_obj: + print("Match found:", match_obj.group()) +else: + print("No match") \ No newline at end of file diff --git a/python_redis.py b/python_redis.py new file mode 100644 index 0000000..a853875 --- /dev/null +++ b/python_redis.py @@ -0,0 +1,55 @@ +# _*_ coding: utf-8 _*_ + +""" +Python操作Redis实现消息的发布与订阅 +""" + +import sys +import time +import redis + +# 全局变量 +conn_pool = redis.ConnectionPool(host="localhost", port=6379, db=1) +conn_inst = redis.Redis(connection_pool=conn_pool) +channel_name = "fm-101.1" + + +def public_test(): + while True: + # 发布消息 + conn_inst.publish(channel_name, "hello " + str(time.time())) + if int(time.time()) % 10 == 1: + conn_inst.publish(channel_name, "over") + time.sleep(1) + + +def subscribe_test(_type=0): + pub = conn_inst.pubsub() + pub.subscribe(channel_name) + + if _type == 0: + # 订阅消息 + for item in pub.listen(): + print("Listen on channel: %s" % item) + if item["type"] == "message" and item["data"].decode() == "over": + print(item["channel"].decode(), "已停止发布") + break + else: + # 另一种订阅模式 + while True: + item = pub.parse_response() + print("Listen on channel: %s" % item) + if item[0].decode() == "message" and item[2].decode() == "over": + print(item[1].decode(), "已停止发布") + break + + # 取消订阅 + pub.unsubscribe() + return + + +if __name__ == '__main__': + if sys.argv[1] == "public": + public_test() + else: + subscribe_test(int(sys.argv[2])) diff --git a/python_schedule.py b/python_schedule.py new file mode 100644 index 0000000..0366a17 --- /dev/null +++ b/python_schedule.py @@ -0,0 +1,53 @@ +# _*_ coding: utf-8 _*_ + +""" +调度的使用 +""" + +import time +import datetime +from threading import Timer +from apscheduler.schedulers.blocking import BlockingScheduler +from apscheduler.schedulers.background import BackgroundScheduler + + +def print_hello(): + print("TimeNow in func: %s" % (datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))) + return + + +if __name__ == "__main__": + # 1. 使用Threading模块中的Timer + # t = Timer(2, print_hello) + # + # print("TimeNow start: %s" % (datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))) + # t.start() + # print("TimeNow end: %s" % (datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))) + # exit() + + # 2. BlockingScheduler:在进程中运行单个任务,调度器是唯一运行的东西, 采用阻塞的方式 + scheduler = BlockingScheduler() + + # 采用固定时间间隔(interval)的方式,每隔5秒钟执行一次 + scheduler.add_job(print_hello, "interval", seconds=5) + + # 采用date的方式,在特定时间只执行一次 + # scheduler.add_job(print_hello, "date", run_date=datetime.datetime.now() + datetime.timedelta(seconds=5)) + + # print("TimeNow start: %s" % (datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))) + # scheduler.start() + # print("TimeNow end: %s" % (datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))) + # exit() + + # 3. BackgroundScheduler: 适合于要求任何在程序后台运行的情况,当希望调度器在应用后台执行时使用。采用非阻塞的方式 + scheduler = BackgroundScheduler() + + # 采用固定时间间隔(interval)的方式,每隔3秒钟执行一次 + scheduler.add_job(print_hello, "interval", seconds=5) + + # 这是一个独立的线程 + # print("TimeNow start: %s" % (datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))) + # scheduler.start() + # print("TimeNow end: %s" % (datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))) + # while True: + # time.sleep(2) diff --git a/python_socket.py b/python_socket.py new file mode 100644 index 0000000..549a5f8 --- /dev/null +++ b/python_socket.py @@ -0,0 +1,80 @@ +# _*_ coding: utf-8 _*_ + +""" +Socket编程 +""" + +import sys +import socket + + +def server_func(port): + """ + 服务端 + """ + # 1. 创建socket对象 + server = socket.socket() + + # 2. 绑定ip和端口 + server.bind(("127.0.0.1", port)) + + # 3. 监听是否有客户端连接 + server.listen(10) + print("服务端已经启动%s端口......" % port) + + # 4. 接收客户端连接 + sock_obj, address = server.accept() + sock_obj.settimeout(3) + print("客户端:%s,超时时间:%s" % (address, sock_obj.gettimeout())) + + while True: + try: + # 5. 接收客户端发送的消息 + recv_data = sock_obj.recv(1024).decode("utf-8") + print("客户端端 -> 服务端: %s" % recv_data) + if recv_data == "quit": + break + + # 6. 给客户端回复消息 + send_data = "received[%s]" % recv_data + sock_obj.send(send_data.encode("utf-8")) + print("服务端 -> 客户端: %s" % send_data) + except Exception as excep: + print("error: ", excep) + + # 7. 关闭socket对象 + sock_obj.close() + server.close() + + +def client_func(port): + """ + 客户端 + """ + # 1. 创建客户端的socket对象 + client = socket.socket() + + # 2. 连接服务端, 需要指定端口和IP + client.connect(("127.0.0.1", port)) + + while True: + # 3. 给服务端发送数据 + send_data = input("客户端>").strip() + client.send(send_data.encode("utf-8")) + if send_data == "quit": + break + + # 4. 获取服务端返回的消息 + recv_data = client.recv(1024).decode("utf-8") + print("服务端 -> 客户端: %s" % recv_data) + + # 5. 关闭socket连接 + client.close() + + +if __name__ == '__main__': + flag = sys.argv[1] + if flag == "server": + server_func(9901) + else: + client_func(9901) diff --git a/test.png b/test.png new file mode 100644 index 0000000..77b79e9 Binary files /dev/null and b/test.png differ