我的博客

修改文件,而不重写不变部分

目录
  1. 修改
  2. 截断

使用 ‘r+’ 参数打开文件,定位文件指针到指定位置然后修改即可。这是写入内容将覆盖原位置的内容,原来其他的内容将保持不变。但是如果修改内容与原内容长度不同时无法采取这种方法。 假设有这样的任务,2亿行的文件每行只有一个a,需要把第三行的a改为b。 使用python的做法(另附两种其他的方法,一种python读取在全部重新写入,一种awk) 1、生成测试文件:

修改

一个2亿行的文件 test_file,每行都只有一个a。文件大小382M。

1
2
3
4
f = open('test_file', 'w')
for i in range(200000000):
f.write('a\n')
f.close()

运行时间 45.916s

2、测试

(1)用r+参数读原文件,直接在原文件上修改

1
2
3
4
5
import os
f = open('test_file', 'r+')
f.seek(4)
f.write('b')
f.close()

运行时间 0m0.014s

(2)读原文件,然后把改动后的结果写入另一个文件:

1
2
3
4
5
6
7
8
9
10
11
fr = open('test_file', 'r')
fw = open('test_file_mod', 'w')
i = 0
for l in fr:
i += 1
if i == 3:
fw.write('b\n')
else:
fw.write(l)
fr.close()
fw.close()

运行时间 1m35.701s

(3)用awk把输出结果到新文件

1
awk '{if(NR==3){print "b"}else{print}}' test_file > test_file_mod

运行时间0m36.397s

使用time命令测试执行时间(取real时间)。三种方法对内存消耗都很小。时间消耗差别很大主要是使用w+时仅写入改动部分,磁盘IO量比另两种方法小很多。 另外测试了使用python按行读完整个test_file的时间是 0m42.689s。 测试使用的代码如下:

1
2
3
4
5
f = open('test_file')
while True:
l = f.readline()
if not l: break
f.close()

在阿里云ECS上进行测试CPU为Intel(R) Xeon(R) CPU E5-2682 v4 @ 2.50GHz

我在知乎的回答:https://www.zhihu.com/answer/605322220

截断

2020 / 04 / 14 更新

今天又遇到一个问题:

一个很大的文件,例如 5 千万行,每行是一个字符 a 。 想删掉最后一行。

重新写入前面不要删除的行,耗时很多。

*

我在 v2ex 的提问:https://www.v2ex.com/t/662192#reply5

根据 @tabris17 的方法,用 python3 实现是:

1
2
3
4
import os
f = os.open('test_file', os.O_RDWR|os.O_CREAT)
os.ftruncate(f, os.path.getsize('test_file') - 2)
os.close(f)

附实验代码:

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
t0 = time.time()
with open('test_file', 'w') as f:
for i in range(50000000):
f.write('a\n')
t1 = time.time()
t1 - t0 # 11.500069618225098
# !wc -l test_file # 50000000

# 重新写入
t0 = time.time()
with open('test_file', 'w') as f:
for i in range(50000000-1):
f.write('a\n')
t1 = time.time()
t1 - t0 # 11.542783975601196
# !wc -l test_file # 49999999

import os
t0 = time.time()
f = os.open('test_file', os.O_RDWR|os.O_CREAT)
os.ftruncate(f, os.path.getsize('test_file') - 2)
os.close(f)
t1 = time.time()
t1 - t0 # 0.000209808349609375
# !wc -l test_file # 49999998

实验环境: Intel(R) Xeon(R) Gold 6161 CPU @ 2.20GHz

Python从后往前读文件

目录
  1. 使用os.path.getsize 获取文件大小
  2. 使用 file_obj.seek 移动文件指针到文件末尾减一处
  3. 每次读取一个字符,并将文件指针向前移动一

代码实现如下:

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
#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import os


def tail_read(f, n):
cur_pos = f.tell()
buf = b''
while n:
b = f.read(1)
buf = b + buf
cur_pos -= 1
if cur_pos < 0: break
f.seek(cur_pos)
n -= 1
return buf


def tail_open(file):
fsize = os.path.getsize(file)
f = open(file, 'rb')
f.seek(fsize - 1)
return f


if __name__ == '__main__':
import sys
f = tail_open(sys.argv[1])
buf = tail_read(f, int(sys.argv[2]))
print (buf)

python2和python3都可运行 测试方法(读取文件名为file的文件的最后100个字节):

  1. 把代码保存成tail_read.py
  2. 执行 python tail_read.py file 100

搭建d3.js开发环境

目录

1、安装node.js 2、初始化项目

创建目录,进入目录,执行命令 npm init -y

然后建立src目录用于存放源码,dist用于存放编译好的代码

3、安装和配置webpack

执行npm install webpack webpack-cli --save-dev

创建文件 webpack.config.js ,写入以下内容

const path = require(‘path’);

module.exports = {
entry: ‘./src/index.js’,
output: {
filename: ‘main.js’,
path: path.resolve(__dirname, ‘dist’)
}
};

修改package.json,在scripts中加入"build": "webpack" 4、安装d3.js

执行 npm install d3 --save

5、编写代码

创建dist/index.html,并写入以下内容

<!doctype html>


Getting Started




创建src/index.js,并写入以下内容

import * as d3 from “d3”;

function SimpleWidget(spec) {
var instance = {}; // <– A
var headline, description; // <– B
instance.render = function () {
var div = d3.select(‘body’).append(“div”);
div.append(“h3”).text(headline); // <– C
div.attr(“class”, “box”)
.attr(“style”, “color:” + spec.color) // <– D
.append(“p”)
.text(description); // <– E
return instance; // <– F
};
instance.headline = function (h) {
if (!arguments.length) return headline; // <– G
headline = h;
return instance; // <– H
};
instance.description = function (d) {
if (!arguments.length) return description;
description = d;
return instance;
};
return instance; // <– I
}
var widget = SimpleWidget({color: “#6495ed”})
.headline(“Simple Widget”)
.description(“This is a simple widget demonstrating functional javascript.”);
widget.render();

6、编译与运行

执行 npm run-script build该命令生成了dist/main.js

在浏览器中打开dist/index.html即可看到代码运行后的效果

参考资料 1、https://webpack.js.org/guides/getting-started/ 2、D3.js数据可视化实战手册 3、https://github.com/NickQiZhu/d3-cookbook/

clang生成抽象语法树

目录

Clang(发音为/ˈklæŋ/类似英文单字clang[1]) 是一个C、C++、Objective-C和Objective-C++编程语言的编译器前端。它采用了LLVM作为其后端,而且由LLVM2.6开始,一起发布新版本。它的目标是提供一个GNU编译器套装(GCC)的替代品,支持了GNU编译器大多数的编译设置以及非官方语言的扩展。官网地址 https://clang.llvm.org 可以用来生成抽象语法树(AST)。 使用命令 clang -Xclang -ast-dump file.cpp 可以生成file.cpp的抽象语法树,输出到标准输出。 但是实际上clang执行的参数是非常复杂的,可以使用 -### 让clang输出他要执行的命令(但不实际执行)

clang -### -Xclang -ast-dump x.cpp

可以看到clang实际会执行两条命令,其中第一条的参数 “-fcolor-diagnostics”可以去掉,这样输出的抽象语法树就不带颜色了。

参考资料:

[1]https://stackoverflow.com/questions/18560019/how-to-view-clang-ast

[2]https://zh.wikipedia.org/wiki/Clang

Thrift简单使用的例子

目录

Apache Thrift软件框架,可以允许不同语言通过网络相互调用,支持的语言有C++,Java,Python,PHP,Ruby,Erlang,Perl,Haskell,C#,Cocoa,JavaScript,Node.js,Smalltalk,OCaml和Delphi等,官方网站是 http://thrift.apache.org/ 使用Apache Thrift的步骤是(此处以python调用java函数为例)

  1. 安装thrift 官方网站有exe和源码下载 http://thrift.apache.org/download
  2. 编写thrift文件,定义接口
  3. 使用thrift编译器由thrift文件产生python的代码和java的代码。
  4. 在自己写python和java的程序中分别import上一步自动生成的代码以及thrift的库

此处以两数相加的函数为例,详细的步骤如下 1、编写thrift文件 文件calculator.thrift

service Calculator {
i32 add(1:i32 num1, 2:i32 num2)
}

serveice Calculator声明了一个服务, i32 add(1: i32 num1, 2:i32 num2) 声明了一个函数add,i32是变量类型——32为有符号整型,add函数需要两个参数num1和num2,类型都是i32,返回值的类型也是i32 2、自动生成代码 一条命令 thrift-0.11.0.exe --gen py calculator.thrift 这是在windows平台下,直接下载一个exe文件就可以,Linux平台好像需要从源码编译 命令的结果是在当前目录下生成了gen-py文件夹,里面有空的__init__.py和calculator文件夹,calculator文件夹里有我们需要的Calculator.py 3、python服务端编写 需要import上一步生成的Calculator.py,在gen-py/calculator/里 需要安装依赖 pip install thrift

import Calculator

from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
from thrift.server import TServer

class CalculatorHandler:
def __init__(self):
self.log = {}

def add(self, n1, n2):
    print('add(%d,%d)' % (n1, n2))
    return n1 + n2

if __name__ == ‘__main__‘:
handler = CalculatorHandler()
processor = Calculator.Processor(handler)
transport = TSocket.TServerSocket(host=’127.0.0.1’, port=9090)
tfactory = TTransport.TBufferedTransportFactory()
pfactory = TBinaryProtocol.TBinaryProtocolFactory()

server = TServer.TSimpleServer(processor, transport, tfactory, pfactory)

# You could do one of these for a multithreaded server
# server = TServer.TThreadedServer(
#     processor, transport, tfactory, pfactory)
# server = TServer.TThreadPoolServer(
#     processor, transport, tfactory, pfactory)

print('Starting the server...')
server.serve()
print('done.')

4、python客户端端编写 同样需要第2步生成的Calculator.py和安装依赖thrift

from gen_py.calc import Calculator

from thrift import Thrift
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol

def main():

# Make socket
transport = TSocket.TSocket('localhost', 9090)

# Buffering is critical. Raw sockets are very slow
transport = TTransport.TBufferedTransport(transport)

# Wrap in a protocol
protocol = TBinaryProtocol.TBinaryProtocol(transport)

# Create a client to use the protocol encoder
client = Calculator.Client(protocol)

# Connect!
transport.open()

sum_ = client.add(1, 1)
print('1+1=%d' % sum_)

transport.close()

if __name__ == ‘__main__‘:
try:
main()
except Thrift.TException as tx:
print(‘%s’ % tx.message)

5、测试 先运行服务端,再执行客户端可以看到服务端打印了客户端发送的请求,客户端也返回了服务端传回的结果

编译安装python 3.7

目录
  1. 下载源码
  2. 安装依赖
  3. configure
  4. 安装
  5. 创建软链(可选)
  6. 配置pip源(可选)

下载源码

下载

wget https://www.python.org/ftp/python/3.7.3/Python-3.7.3.tgz

解压

tar -xzvf Python-3.7.3.tgz

安装依赖

yum install openssl-devel bzip2-devel expat-devel gdbm-devel sqlite-devel libffi-devel

configure

./configure --enable-optimizations

安装

1
2
make
make install

创建软链(可选)

我一般喜欢把python3.7链接为py这与windows下的名称一致

ln /usr/local/bin/python3.7 /usr/local/bin/py -s

这样就可以用 py 来启动python3.7了

配置pip源(可选)

pip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

我一般使用清华源,速度快且支持IPv6

Nginx + gunicorn部署django项目(https)

目录
  1. 编译安装nginx
  2. 配置nginx
    1. 80端口的设置
    2. 配置域名
    3. 配置转发
    4. 配置静态文件路径
    5. 配置ssl
    6. 把http重定向到https
    7. 示例
  3. 获取django静态文件并添加到nginx的静态目录下
  4. 部署django

测试环境

centos 7.6 nginx1.17.0

Ubuntu 16.04 nginx1.10.3

编译安装nginx

CentOS 7 下编译安装nginx并配置服务

配置nginx

80端口的设置

listen 80 default_server; listen [::]:80 default_server;

配置域名

server_name codeplot.top;

配置转发

1
2
3
4
5
6
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

配置静态文件路径

1
2
3
location /static {
alias html/static/;
}

配置ssl

ssl_certificate cert/1539002028323.pem; ssl_certificate_key cert/1539002028323.key;

ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on;

把http重定向到https

return 301 https://$server_name$request_uri;

示例

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
http {
server {
listen 443 ssl;
server_name codeplot.top;
ssl_certificate cert/cert.crt;
ssl_certificate_key cert/private.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://127.0.0.1:8001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /static {
alias html/static/;
}
}

server {
listen 80;
server_name codeplot.top;
return 301 https://$server_name$request_uri;
}
}

获取django静态文件并添加到nginx的静态目录下

1.在settings.py文件中添加配置; STATIC_ROOT 指示把静态文件放到哪里

例如 STATIC_ROOT = os.path.join(BASE_DIR, 'static_export')

2.执行命令,读取所有static文件到项目目录中

python3 manage.py collectstatic

3.把这些系统static文件连同项目的static文件一起拷贝到nginx的静态目录下(上一步设置的目录)

部署django

  • 安装依赖

pip install gevent gunicorn

  • 启动gunicorn

gunicorn --worker-class=gevent 应用名称.wsgi:application

尝试百度EasyDL-MNIST

目录

EasyDL使用非常简单主要是需要找到合适的数据并上传,然后模型的训练,测试,发布,部署都是点一下就自动做了。 我选择 MNIST 作为测试数据,转换格式后上传到EasyDL上,使用train的50000张图片进行训练,耗时大概半天,top1准确率97.45%,top5准确率99.79%。 我的数据 链接: https://pan.baidu.com/s/1KwLV0-S3R91KGzxvUZz90A 提取码: 36ps 生成数据的代码: 要先安装 scipy和pillow pip install scipy pillow 下载代码 input_data.py : https://paste.ubuntu.com/p/jvhTc7YzCT/ 下载代码 https://paste.ubuntu.com/p/FQy7QzkMVx/ 这个代码需要使用input_data.py 所以上面那个代码要命名正确,并与这个代码放在同一目录下。

打水

目录

我住在公寓的15层,开水房在12层,晚上打热水的人很多,水流却极小,我打了一瓶用了半个多小时,活像在山上接泉水。青岛大学后面的浮山上有很多泉水,清早上山总会遇到上山打水的人。有的拿着大大小小的塑料瓶,或者背着大包往山里去,有的人已经满载而归。那是我上大学二年级的时候,我觉得早起爬浮山会带来好运,于是在4级前,在比赛前我都会早起吃饭,再去山上逛一下。直到大三的时候,6级两次都没过,GRE和托福也不顺利。或许是我那时太忙了而忽视了浮山。大学生活是多么美好,青岛是多么温暖的城市,只是我没能好好品味在青岛那么多个日日夜夜。有时候我太着急了,以至于忽视了很多重要的事情。

山海之间

西游记写秋景的曲

目录

水痕收,山骨瘦。红叶纷飞,黄花时候,霜晴觉夜长,月白穿窗透。家家烟火夕阳多,处处湖光寒水溜。白蘋香,红蓼茂。桔绿橙黄,柳衰谷秀。荒村雁落碎芦花,野店鸡声收菽豆。