柴君

柴君 查看完整档案

填写现居城市  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 个人简介什么都没有

个人动态

柴君 回答了问题 · 2018-03-19

Flask的简单开源项目推荐?

基于flask开发类似gitbook的知识管理网站
github地址:https://github.com/chaijunit/...

关注 21 回答 8

柴君 发布了文章 · 2018-03-16

基于flask实现开发类似gitbook项目:beibq

项目源码:https://github.com/chaijunit/...

beibq是基于flask开发的开源书籍博客。

因为很多博客系统都是以文章的形式为主;如果记录的文章变多了,还需要进行分类,而且查找以前写过的某篇文章会比较麻烦。

beibq是用写书的方式来写博客,因为书籍本身就具有分类功能,就算记录的内容变多了也不觉得乱,而且在阅读时通过点击书籍目录很方便的切换到其他章节。

安装配置

搭建好网站后,用浏览器访问,会出现配置界面

在线写书

beibq的编辑器支持Markdown,Markdown是一个标记语言,只需要几个简单的标记符号就能转化成丰富的HTML格式,特别适合写博客。关于Markdown的具体介绍:Markdown 语法说明

beibq的编辑器界面简洁、操作简单,能够通过工具栏或快捷键方式输入Markdown标记符号,有效的提高写作效率;编辑器的目录区支持章节拖拉,可以调整章节顺序。

编辑器例子:在线写书

beibq的编辑器是纯js实现,我单独将它开源出来:bookeditor

写好书籍后点击发布,就能在首页上看到最新书籍动态

界面

beibq的界面简洁、美观、易用。阅读博客时,就像看书一样,界面包含书籍目录;这样只要点击目录的某个章节就能很方便切换到其他章节。

为了提高切换章节效率,当点击目录中某个章节,通过ajax异步请求章节内容,这样可以不仅提高页面刷新速度而且具有很好的阅读体验;

其实使用ajax异步请求章节会出现一个问题,当网络延迟高,用户短时间内点击多个章节,会导致页面显示混乱;为了解决这个问题,我设计一个队列,将用户点击章节时将该事件缓存到队列中,如果短时间内接收多个点击事件,我其实只请求队列中最后的一个事件。

beibq还可以自动适配移动端界面,用户可以在移动设备上阅读。

安装使用

1. 安装mysql

beibq使用的数据库是mysql,安装前需要先安装mysql

我使用的是centos,安装方法可以参考该文档:Installing MySQL on Linux Using the MySQL Yum Repository

2. 安装依赖包

pip install -r requirements.txt

3. 启动程序

python manage.py runserver -h 0.0.0.0

4. 配置站点

在浏览器中输入http://127.0.0.1:5000

第一次访问会跳转到配置界面,根据指示配置站点信息后就能使用beibq

查看原文

赞 6 收藏 5 评论 1

柴君 发布了文章 · 2017-11-08

sanic中文文档

入门指南

Install Sanic:python3 -m pip install sanic
example

from sanic import Sanic
from sanic.response import text
app = Sanic(__name__)
@app.route("/")
async def test(request):
    return text('Hello world!')
app.run(host="0.0.0.0", port=8000, debug=True)

路由

路由允许用户为不同的URL端点指定处理程序函数。

demo:

from sanic.response import json
@app.route("/")
async def test(request):
    return json({ "hello": "world" })

url http://server.url/ 被访问(服务器的基本url),最终'/'被路由器匹配到处理程序函数,测试,然后返回一个JSON对象。

请求参数

请求参数

要指定一个参数,可以用像这样的角引号<PARAM>包围它。请求参数将作为关键字参数传递给路线处理程序函数。
demo

from sanic.response import text
@app.route('/tag/<tag>')
async def tag_handler(request, tag):
    return text('Tag - {}'.format(tag))

为参数指定类型,在参数名后面添加(:类型)。如果参数不匹配指定的类型,Sanic将抛出一个不存在的异常,导致一个404页面
demo:

from sanic.response import text
@app.route('/number/<integer_arg:int>')
async def integer_handler(request, integer_arg):
    return text('Integer - {}'.format(integer_arg))
@app.route('/number/<number_arg:number>')
async def number_handler(request, number_arg):
    return text('Number - {}'.format(number_arg))
@app.route('/person/<name:[A-z]+>')
async def person_handler(request, name):
    return text('Person - {}'.format(name))
@app.route('/folder/<folder_id:[A-z0-9]{0,4}>')
async def folder_handler(request, folder_id):
    return text('Folder - {}'.format(folder_id))

请求类型

路由装饰器接受一个可选的参数,方法,它允许处理程序函数与列表中的任何HTTP方法一起工作。
demo_1
from sanic.response import text
@app.route('/post', methods=['POST'])
async def post_handler(request):
    return text('POST request - {}'.format(request.json))
@app.route('/get', methods=['GET'])
async def get_handler(request):
    return text('GET request - {}'.format(request.args))
demo_2
from sanic.response import text
@app.post('/post')
async def post_handler(request):
    return text('POST request - {}'.format(request.json))
@app.get('/get')
async def get_handler(request):
    return text('GET request - {}'.format(request.args))

增加路由

from sanic.response import text
# Define the handler functions
async def handler1(request):
    return text('OK')
async def handler2(request, name):
    return text('Folder - {}'.format(name))
async def person_handler2(request, name):
    return text('Person - {}'.format(name))
# Add each handler function as a route
app.add_route(handler1, '/test')
app.add_route(handler2, '/folder/<name>')
app.add_route(person_handler2, '/person/<name:[A-z]>', methods=['GET'])

url_for

Sanic提供了一个urlfor方法,根据处理程序方法名生成url。避免硬编码url路径到您的应用程序
demo

@app.route('/')
async def index(request):
    # generate a URL for the endpoint `post_handler`
    url = app.url_for('post_handler', post_id=5)
    # the URL is `/posts/5`, redirect to it
    return redirect(url)
@app.route('/posts/<post_id>')
async def post_handler(request, post_id):
    return text('Post - {}'.format(post_id))

Notice:

  • 给url equest的关键字参数不是请求参数,它将包含在URL的查询字符串中。例如:
url = app.url_for('post_handler', post_id=5, arg_one='one', arg_two='two')
# /posts/5?arg_one=one&arg_two=two
  • 所有有效的参数必须传递给url以便构建一个URL。如果没有提供一个参数,或者一个参数与指定的类型不匹配,就会抛出一个URLBuildError
    可以将多值参数传递给url
url = app.url_for('post_handler', post_id=5, arg_one=['one', 'two'])
# /posts/5?arg_one=one&arg_one=two

WebSocket routes(网络套接字路由)

websocket 可以通过装饰路由实现
demo:

@app.websocket('/feed')
async def feed(request, ws):
    while True:
        data = 'hello!'
        print('Sending: ' + data)
        await ws.send(data)
        data = await ws.recv()
        print('Received: ' + data)
        
另外,添加 websocket 路由方法可以代替装饰器

async def feed(request, ws):
    pass
app.add_websocket_route(my_websocket_handler, '/feed')

响应( response )

text

from sanic import response
@app.route('/text')
def handle_request(request):
    return response.text('Hello world!')

HTML

from sanic import response
@app.route('/html')
def handle_request(request):
    return response.html('<p>Hello world!</p>')

JSON

from sanic import response
@app.route('/json')
def handle_request(request):
    return response.json({'message': 'Hello world!'})

File

from sanic import response
@app.route('/file')
async def handle_request(request):
    return await response.file('/srv/www/whatever.png')

Streaming

from sanic import response
@app.route("/streaming")
async def index(request):
    async def streaming_fn(response):
        response.write('foo')
        response.write('bar')
    return response.stream(streaming_fn, content_type='text/plain')

File Streaming

对于大文件,文件和流的组合

from sanic import response
@app.route('/big_file.png')
async def handle_request(request):
    return await response.file_stream('/srv/www/whatever.png')

Redirect

from sanic import response
@app.route('/redirect')
def handle_request(request):
    return response.redirect('/json')

Raw

没有进行编码的响应

from sanic import response
@app.route(‘/raw ’)
def handle_request(request):
return response.raw(‘ raw data ’)

Modify headers or status

要修改头或状态代码,将标题或状态参数传递给这些函数

from sanic import response
@app.route(‘/json ’)
def handle_request(request):
return response.json(
{‘ message ’: ‘ Hello world!’},
headers={‘ X-Served-By ’: ‘ sanic ’},
status=200
)

更多的内容:Sanic 中文文档

查看原文

赞 0 收藏 2 评论 0

柴君 发布了文章 · 2017-11-08

android六种方法保证service不被杀死

一、onStartCommand方法,返回START_STICKY

  在运行onStartCommand后service进程被kill后,那将保留在开始状态,但是不保留那些传入的intent。不久后service就会再次尝试重新创建,因为保留在开始状态,在创建 service后将保证调用onstartCommand。如果没有传递任何开始命令给service,那将获取到null的intent。

   【结论】 手动返回START_STICKY,亲测当service因内存不足被kill,当内存又有的时候,service又被重新创建,比较不错,但是不能保证任何情况下都被重建,比如进程被干掉了…. 

二、提升service优先级

  在AndroidManifest.xml文件中对于intent-filter可以通过android:priority = “1000”这个属性设置最高优先级,1000是最高值,如果数字越小则优先级越低,同时适用于广播。

三、提升service进程优先级

  Android中的进程是托管的,当系统进程空间紧张的时候,会依照优先级自动进行进程的回收。Android将进程分为6个等级,它们按优先级顺序由高到低依次是:
1.前台进程( FOREGROUND_APP)
2.可视进程(VISIBLE_APP )

次要服务进程(SECONDARY_SERVER )
4.后台进程 (HIDDEN_APP)
5.内容供应节点(CONTENT_PROVIDER)
6.空进程(EMPTY_APP)
当service运行在低内存的环境时,将会kill掉一些存在的进程。因此进程的优先级将会很重要,可以使用startForeground 将service放到前台状态。这样在低内存时被kill的几率会低一些。
在onStartCommand方法内添加如下代码:

Notification notification = new Notification(R.drawable.ic_launcher,

     getString(R.string.app_name), System.currentTimeMillis());
     PendingIntent pendingintent = PendingIntent.getActivity(this, 0,
     new Intent(this, AppMain.class), 0);
     notification.setLatestEventInfo(this, "uploadservice", "请保持程序在后台运行",
     pendingintent);
     startForeground(0x111, notification);

注意在onDestroy里还需要stopForeground(true),运行时在下拉列表会看到自己的APP在:
【结论】如果在极度极度低内存的压力下,该service还是会被kill掉,并且不一定会restart

四、onDestroy方法里重启service

  直接在onDestroy()里startService 
  或
  service +broadcast 方式,就是当service走ondestory的时候,发送一个自定义的广播,当收到广播的时候,重新启动service;

【结论】当使用类似口口管家等第三方应用或是在setting里-应用-强制停止时,APP进程可能就直接被干掉了,onDestroy方法都进不来,所以还是无法保证~.~

五、监听系统广播判断Service状态

  通过系统的一些广播,比如:手机重启、界面唤醒、应用状态改变等等监听并捕获到,然后判断我们的Service是否还存活,别忘记加权限啊。

六、将APK安装到/system/app,变身系统级应用

更多:

查看原文

赞 0 收藏 4 评论 1

柴君 回答了问题 · 2017-11-08

Android开发有哪些常用设计模式?

面向对象的六大原则

  • 单一职责原则
      所谓职责是指类变化的原因。如果一个类有多于一个的动机被改变,那么这个类就具有多于一个的职责。而单一职责原则就是指一个类或者模块应该有且只有一个改变的原因。通俗的说,即一个类只负责一项职责,将一组相关性很高的函数、数据封装到一个类中。
  • 开闭原则
      对于扩展是开放的,这意味着模块的行为是可以扩展的。当应用的需求改变时,我们可以对模块进行扩展,使其具有满足那些改变的新行为。

  对于修改是关闭的,对模块行为进行扩展时,不必改动模块的源代码。

  通俗的说,尽量通过扩展的方式实现系统的升级维护和新功能添加,而不是通过修改已有的源代码。

  • 里氏替换原则
      使用“抽象(Abstraction)”和“多态(Polymorphism)”将设计中的静态结构改为动态结构,维持设计的封闭性。任何基类可以出现的地方,子类一定可以出现。

  在软件中将一个基类对象替换成它的子类对象,程序将不会产生任何错误和异常,反过来则不成立。在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象。

  • 依赖倒置原则
      高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。抽象不应该依赖于具体实现,具体实现应该依赖于抽象。

  
  程序要依赖于抽象接口,不要依赖于具体实现。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合(各个模块之间相互传递的参数声明为抽象类型,而不是声明为具体的实现类)。

  • 接口隔离原则
      一个类对另一个类的依赖应该建立在最小的接口上。其原则是将非常庞大的、臃肿的接口拆分成更小的更具体的接口。
  • 迪米特原则
      又叫作最少知识原则,就是说一个对象应当对其他对象有尽可能少的了解。

  通俗地讲,一个类应该对自己需要耦合或调用的类知道得最少,不关心被耦合或调用的类的内部实现,只负责调用你提供的方法。

设计模式有16种,内容很多,我这里就直接发链接

  1. 单例模式 (常用)
  2. 工厂模式 (常用)
  3. 适配器模式 (常用)
  4. 责任链模式
  5. 观察者模式 (常用)
  6. 建造者模式 (常用)
  7. 备忘录模式
  8. 原型模式
  9. 策略模式
  10. 模板模式
  11. 代理模式
  12. 解释器模式
  13. 状态模式
  14. 命令模式
  15. 迭代模式
  16. 组合模式

关注 5 回答 4

柴君 回答了问题 · 2017-11-08

解决有哪些学习 Rust 的在线教程?

关注 13 回答 8

柴君 发布了文章 · 2017-11-02

NodeQuant:一个基于Node.js的开源量化交易平台

NodeQuant:一个基于Node.js的开源量化交易平台

NodeQuant的愿景

让Node.js社区轻巧地开发和部署量化金融交易程序,成为一个简单、高效、可依赖的量化交易平台:NodeQuant开发文档

NodeQuant如何支持量化交易

  • 一个账号 —— 多策略,支持一个账号多个策略的量化产品模式
  • 一个策略 —— 多合约,支持套利
  • 一个策略 —— 多市场,支持跨市场交易、套利
  • 多个市场 —— NodeQuant 将会全部集成上期CTP、飞鼠Sgit 、富途证券、盈透证券IB的程序化API交易客户端,可在多市场中交易和套利
  • 上期CTP —— 中金所、上期所、大商所、郑商所的商品期货、期权合约
  • 飞鼠Sgit —— 期货、上海黄金交易所的贵金属现货
  • 富途证券 —— 港股、美股、A股
  • 盈透证券 —— 全球24个国家100多个市场中心的股票、期权、期货、外汇等产品
  • 使用JavaScript语言开发量化交易策略。与C++相比不需要策略研究员处理琐碎但重要的内存管理问题。Node.js的速度也非常快,与C++处于同一个级别速度,且入门简单,能够快速开发程序。

NodeQuant简介

国内的量化交易平台大多是C、C++、C#、Java、Python等语言编写量化策略。从事量化交易的人员在学会金融数据的分析的同时也要学好一门编程语言,往往学好一门编程语言对于很多人是一个不小的门槛。JavaScript语言是一门简单轻便的脚本语言,学习和编写JavaScript程序都非常简单。脚本语言具有弱类型的特点,不需要开发者在编写程序的过程中适配各种数据类型,入门快速。

JavaScript有大量的开发者,它是GitHub上最热门的编程语言。JavaScript语言借助Node.js运行环境,可以使得JavaScript也可以像C++、C#等高级语言一样运行在服务器端,可以进行读写文件,数据库,访问网络等操作。

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。

Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。

Node.js 的包管理器 npm,是全球最大的开源库生态系统。使用npm可以找到各种各样的第三方库,开发者可以集成到自己的程序当中。

量化金融交易程序是一种是基于高频网络访问和各种事件(OnTick,OnOrder,OnTrade)的数据密集型程序。由于Node.js非阻塞的,事件驱动的 I/O 操作等特点,使得它处理数据密集型实时应用时非常轻巧高效,可以认为是数据密集型分布式部署环境下的实时应用系统的完美解决方案。

使用Node.js来编写和运行量化交易策略程序是一个非常好的解决方案。

这就是NodeQuant量化金融交易平台诞生的背景。

NodeQuant 最新特性

  • 支持上期CTP的API客户端(Windows Node.js-8-32位、Windows Node.js-8-64位、Linux x64 Node.js-8)。可交易中金所、上期所、大商所、郑商所的所有期货品种合约
  • 支持飞鼠Sgit的API客户端(Windows Node.js-8-32位、Linux x64 Node.js-8-64位)。可交易中金所、上期所、大商所、郑商所的所有期货品种合约,并且可交易上海黄金交易所的现货合约。可程序化交易现货黄金、白银。
  • 支持一个账号 —— 多策略,支持一个账号多个策略的量化产品模式
  • 支持一个策略 —— 多合约,支持趋势、套利交易
  • 支持一个策略 —— 多市场,支持跨市场交易、套利
  • 支持交易K线周期:秒、分钟、小时
  • 支持交易所支持的多种类型订单:限价单,市价单,FAK单,FOK单,条件单。可灵活使用于趋势,套利,钓鱼等交易策略
  • 支持盘后自动计算策略盈亏净值
  • 极速响应实盘交易。使用Redis内存数据库,记录与查询交易信息
  • 支持可视化策略运行状态。使用Redis数据库Windows图形化客户端查看策略运行交易数据,可以查看本地和云服务器的策略运行状态
  • 无人值守。支持配置非交易时间自动停止,交易时间自动启动交易策略
  • 支持打包加密策略
  • 更小的滑点成本。Windows系统中对CTP交易客户端进行测试,系统内Tick-To-FinishSendOrder平均耗时:1.5ms(基于python的vn.py平均耗时22.6ms)

NodeQuant 2.0即将来到的特性

  • 支持连接Tick数据行情服务器,使得策略可预先加载Tick,分钟行情数据。方便策略获取预处理数据
  • 支持策略运行异常邮件通知

详情请看:NodeQuant开发文档

查看原文

赞 8 收藏 13 评论 1

柴君 回答了问题 · 2017-06-15

解决行python爬虫时,MySQL版本是5.7,总是报错

如果其他的utf8字符串写入mysql也没问题 那么肯定是你爬虫时候 请求下来的内容有问题 一般有两种情况会出现这种问题:

  • 爬虫内容不是utf8 这种情况很好处理 根据编码格式转下就行
  • 爬虫内容被gzip压缩 这种情况爬下来的内容是乱码的 不管转换成什么编码都是乱码,所以要先将内容解压后,再转换成utf8,解压方法请看 beautifulsoup爬虫出现乱码

关注 5 回答 5

认证与成就

  • 获得 16 次点赞
  • 获得 3 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 3 枚铜徽章

擅长技能
编辑

(゚∀゚ )
暂时没有

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2016-11-24
个人主页被 571 人浏览