Python通过配置文件动态修改全局变量

本文学习如何通过配置文件动态修改全局变量。

看代码main.py:

1
2
3
4
5
import conf
print(conf.defaultpath)
conf.load_conf()
print("*" * 50)
print(conf.defaultpath)

和代码conf.py:

1
2
3
4
5
6
defaultpath = "/home/long/"


def load_conf():
    data = "defaultpath = '/home/long/test'"
    exec data in globals(), globals()

运行结果:

>> long@happytime:~/exectest$ python main.py
>> /home/long/
>> **************************************************
>> /home/long/test

通过load_conf()函数,我们的程序动态修改了全局变量。通过这样的方式就可以实现初始按照默认配置、必要时通过配置文件对全局变量进行修改了。

Python命令行解析模块optparse

本文学习命令行参数解析的模块optparse。这个模块在Python2.7之后已经不鼓励使用,并由argparse所替代。

我们稍微改了一点Dpark中的源码如下opttest.py:

import optparse

parser = optparse.OptionParser(usage="Usage: %prog [options] [args]")
# 禁用散置参数,参数解析到第一个非选项参数为止,之后的就不再作为选项解析
parser.disable_interspersed_args()
# 选项组
group = optparse.OptionGroup(parser, "Dpark Options")
group.add_option("-m", "--master", type="string", default="local",
                 help="master of Mesos: local, process, " +
                 "host[:port], or mesos: //")
group.add_option("-p", "--parallel", type="int", default=0,
                 help="number of processes")
group.add_option("-c", "--cpus", type="float", default=1.0,
                 help="cpus used per task")
group.add_option("-M", "--mem", type="float", default=1000.0,
                 help="memory used per task")
group.add_option("-g", "--group", type="string", default="",
                 help="which group of machines")
group.add_option("--err", type="float", default=0.0,
                 help="acceptable ignored error record ratio (0.01%)")
group.add_option("--snapshot_dir", type="string", default="",
                 help="shared dir to keep snapshot of RDDs")
group.add_option("--conf", type="string",
                 help="path for configuration file")
group.add_option("--self", action="store_true",
                 help="user self as exectuor")
group.add_option("--profile", action="store_true",
                 help="do profiling")
group.add_option("--keep-order", action="store_true",
                 help="deprecated, always keep order")
parser.add_option_group(group)
# 独立选项
parser.add_option("-q", "--quiet", action="store_true")
parser.add_option("-v", "--verbose", action="store_true")
# 读取参数
options, args = parser.parse_args()
print(options)

我们执行代码:

>> long@happytime:~/opttest$ python3 opttest.py
>> {'keep_order': None, 'self': None, 'group': '', 'parallel': 0, 'conf': None, 'snapshot_dir': '', 'cpus': 1.0, 'quiet': None, 'err': 0.0, 'master': 'local', 'mem': 1000.0, 'profile': None, 'verbose': None}
>> long@happytime:~/opttest$ python3 opttest.py -p 10
>> {'group': '', 'verbose': None, 'mem': 1000.0, 'self': None, 'conf': None, 'cpus': 1.0, 'keep_order': None, 'err': 0.0, 'quiet': None, 'snapshot_dir': '', 'profile': None, 'parallel': 10, 'master': 'local'}
>> long@happytime:~/opttest$ python3 opttest.py -v
>> {'snapshot_dir': '', 'conf': None, 'err': 0.0, 'self': None, 'profile': None, 'quiet': None, 'master': 'local', 'verbose': True, 'group': '', 'cpus': 1.0, 'parallel': 0, 'keep_order': None, 'mem': 1000.0}
>> long@happytime:~/opttest$ python3 opttest.py --help
>> Usage: opttest.py [options] [args]
>>
>> Options:
>>   -h, --help            show this help message and exit
>>   -q, --quiet
>>   -v, --verbose
>>
>>   Dpark Options:
>>     -m MASTER, --master=MASTER
>>                         master of Mesos: local, process, host[:port], or
>>                         mesos: //
>>     -p PARALLEL, --parallel=PARALLEL
>>                        number of processes
>>     -c CPUS, --cpus=CPUS
>>                         cpus used per task
>>     -M MEM, --mem=MEM   memory used per task
>>     -g GROUP, --group=GROUP
>>                         which group of machines
>>     --err=ERR           acceptable ignored error record ratio (0.01%)
>>     --snapshot_dir=SNAPSHOT_DIR
>>                         shared dir to keep snapshot of RDDs
>>     --conf=CONF         path for configuration file
>>     --self              user self as exectuor
>>     --profile           do profiling
>>     --keep-order        deprecated, always keep order

通过optparse,我们可以设定参数标识、参数默认值、参数类型和帮助信息等等内容。这样我们就可以让程序具有很强的适应性,最典型的应用就是Linux下各种命令行工具,强大的同时不失灵活。

Python构造对象编号自动加一

这是一个Python中类方法的使用案例。

我们如何实现每生成一个对象,它的编号就自动加1呢?

看代码:

class Stu:

    def __init__(self):
        self.id = self.getnewid()
        self.name = "写程序的龙龙"
        self.url = "https://codinglonglong.github.io"

    def __str__(self):
        return "id: " + str(self.newid) + "\n" + \
            "name: " + str(self.name) + "\n" + \
            "blog: " + str(self.url)

    newid = 0

    @classmethod
    def getnewid(cls):
        cls.newid = cls.newid + 1
        return cls.newid


stu1 = Stu()
print(stu1)
print("*" * 50)
stu2 = Stu()
print(stu2)

运行程序,得到如下结果:

>> long@mylife:~$ python3 test.py
>> id: 1
>> name: 写程序的龙龙
>> blog: https://codinglonglong.github.io
>> **************************************************
>> id: 2
>> name: 写程序的龙龙
>> blog: https://codinglonglong.github.io

我们看到,每初始化一个对象,对象的id就增加了1。

UEditor的Python迁移

UEditor http://ueditor.baidu.com/website/ 是由百度前端研发部开发的所见即所得开源富文本web编辑器,官方文档 http://fex.baidu.com/ueditor/ 提供了JSP、PHP、ASP.net和ASP的后端部署,没有Python的。而我们的网站建设中,需要用到UEditor,所以研究了一下UEditor的Python迁移,主要是针对Bottle框架的Python迁移。

代码结构如下:

>> long@happytime:~/development/frameworktest$ ls
>> bll  db   documentations  models  readme.md  static  views
>> dal  dml  main.py         pages   rpl        tools
>> long@happytime:~/development/frameworktest$ cd static
>> long@happytime:~/development/frameworktest/static$ ls
>> css  files  images  js  ueditor
>> long@happytime:~/development/frameworktest/static$ cd ueditor/
>> long@happytime:~/development/frameworktest/static/ueditor$ ls
>> dialogs     lang    third-party         umeditor.min.js
>> index.html  themes  umeditor.config.js

1、把UEditor的代码放到项目的static/ueditor中,放置结构如上图。

2、main.py完成静态资源文件的映射,代码如下:

1
2
3
4
@route("/static/<path:re:.*>")
def getstaticdir(path):
    path = "./static/" + str(path)
    return static_file(path, root=".")

3、修改umeditor.config.js:

//图片上传配置区
,imageUrl: "/imageup"             //图片上传提交地址
,imagePath: ""                     //图片修正地址,引用了fixedImagePath,如有特殊需求,可自行配置
,imageFieldName:"upfile"                   //图片数据的key,若此处修改,需要在后台对应文件修改对应参数

4、将UEditor放到页面上,views下任意一个tpl文件中:

<link href="/static/ueditor/themes/default/css/umeditor.css" type="text/css" rel="stylesheet">
<script type="text/javascript" src="/static/ueditor/third-party/jquery.min.js"></script>
<script type="text/javascript" charset="utf-8" src="/static/ueditor/umeditor.config.js"></script>
<script type="text/javascript" charset="utf-8" src="/static/ueditor/umeditor.min.js"></script>
<script type="text/javascript" src="/static/ueditor/lang/zh-cn/zh-cn.js"></script>

<div id="editor">
<script type="text/plain" id="myEditor" style="width:1000px;height:240px;">
<p>这里我可以写一些输入提示</p>
</script>
<script type="text/javascript">
var um = UM.getEditor('myEditor');
function getAllHtml() {
    var arr = [];
    arr.push(UM.getEditor('myEditor').getAllHtml());
    window.location.href="/getallhtml?contentstr=" + encodeURIComponent(arr.join("\n"));
}
function getContent() {
    var arr = [];
    arr.push(UM.getEditor('myEditor').getContent());
    window.location.href="/getallhtml?contentstr=" + encodeURIComponent(arr.join("\n"));
}
function getContentTxt() {
    var arr = [];
    arr.push(UM.getEditor('myEditor').getContentTxt());
    window.location.href="/getallhtml?contentstr=" + encodeURIComponent(arr.join("\n"));
}
function hasContent() {
    var arr = [];
    arr.push(UM.getEditor('myEditor').hasContents());
    alert(arr.join("\n"));
}
function setFocus() {
    UM.getEditor('myEditor').focus();
}
function doBlur(){
    um.blur();
}
function setContent() {
    UM.getEditor('myEditor').setContent('欢迎使用umeditor');
}
function setDisabled() {
    UM.getEditor('myEditor').setDisabled('fullscreen');
    disableBtn("enable");
}
function setEnabled() {
    UM.getEditor('myEditor').setEnabled();
    enableBtn();
}
</script>
</div>
<div id="btns">
    <table>
        <tr>
            <td>
                <button class="btn" onclick="getAllHtml()">获得整个html的内容</button>&nbsp;
                <button class="btn" onclick="getContent()">获得内容</button>&nbsp;
                <button class="btn" onclick="getContentTxt()">获得纯文本</button>&nbsp;
                <button class="btn" onclick="hasContent()">判断是否有内容</button>
            </td>
        </tr>
        <tr>
            <td>
                <button class="btn" onclick="setFocus()">编辑器获得焦点</button>&nbsp;
                <button class="btn" onclick="doBlur()">编辑器取消焦点</button>&nbsp;
                <button class="btn" onclick="setContent()">插入给定的内容</button>&nbsp;
                <button class="btn" onclick="setEnabled()">可以编辑</button>&nbsp;
                <button class="btn" onclick="setDisabled()">不可编辑</button>
            </td>
        </tr>
        <tr>
            <td>
                <button class="btn" onclick="UM.getEditor('myEditor').setHide()">隐藏编辑器</button>&nbsp;
                <button class="btn" onclick="UM.getEditor('myEditor').setShow()">显示编辑器</button>&nbsp;
                <button class="btn" onclick="UM.getEditor('myEditor').setHeight(300)">设置编辑器的高度为300</button>&nbsp;
                <button class="btn" onclick="UM.getEditor('myEditor').setWidth(1200)">设置编辑器的宽度为1200</button>
            </td>
        </tr>
    </table>
</div>

注意,由于要提交的内容本身含有特殊字符,如空格。需要用javascript的encodeURIComponent函数进行编码。

5、编写后台接收提交的代码main.py或者rpl下的任意一个py文件中:

@route('/imageup', method="POST")
def imageup():
    fileobj = request.POST.upfile
    filename = fileobj.filename
    content = fileobj.file.read()
    imagedir = os.getcwd() + "/static/images"
    webimagedir = "/static/images"
    newimagename = str(uuid.uuid1()) + filename
    imageurl = imagedir + "/" + newimagename
    webimageurl = webimagedir + "/" + newimagename
    fout = open(imageurl, "wb")
    fout.write(content)
    fout.close()
    return """{'url':'""" + str(webimageurl) + """',
    'title': '""" + str(newimagename) + """',
    'original':'""" + str(filename) + """',
    'state':'SUCCESS'}"""


@route('/getallhtml')
def getallhtml():
    contentstr = request.GET.contentstr
    resultstr = urllib.parse.unquote(contentstr)
    print(resultstr)


@route('/getcontent')
def getcontent():
    contentstr = request.GET.contentstr
    resultstr = urllib.parse.unquote(contentstr)
    print(resultstr)


@route('/getcontenttxt')
def getcontenttxt():
    contentstr = request.GET.contentstr
    resultstr = urllib.parse.unquote(contentstr)
    print(resultstr)

可以看到,由于之前的javascript中进行了编码,所以这里要用urllib.parse.unquote进行解码。而上传的图片,会放到/static/images目录下。

至此就完成了UEditor的Python迁移,可以正常在Bottle框架上完成工作。

注:例子中使用的是UEditor的缩减版UMeditor。

Linux添加用户和切换用户

添加用户

>> sudo adduser long

这时系统会交互输入一些基本信息,按需要输入就可以。但是新添加的用户默认没有执行sudo的权限。

赋予用户执行sudo的权限

>> sudo usermod  -a -G sudo long

切换用户

>> su - long

这样就进入long的用户环境了,毕竟一直用root工作不是很安全,还是建立一个普通用户比较保险。


这里再多说一点关于su -、su和sudo的区别:

su - : 完全意义上的切换用户,包括环境变量配置之类的。

su : 只是切换了当前工作的用户,环境变量配置之类的不变。

sudo : 赋予用户执行部分高级功能的权限。

Ubuntu14.04上安装JDK

1、访问 http://www.oracle.com/technetwork/java/javase/downloads/index.html , 下载Java Platform (JDK)。

选择Linux x64 165.17 MB jdk-8u40-linux-x64.tar.gz

2、解压

>> tar -zxvf jdk-8u40-linux-x64.tar.gz

3、新建目录

>> cd /usr/lib
>> sudo mkdir jvm
>> cd jvm

4、把解压好的文件夹放入jvm目录

>> sudo mv ~/Downloads/jdk1.8.0_40 .

5、修改环境变量

>> gedit ~/.bashrc

添加如下内容:

export JAVA_HOME=/usr/lib/jvm/jdk1.8.0_40
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
>> source ~/.bashrc

6、更新命令配置

>> sudo update-alternatives --install /usr/bin/java java /usr/lib/jvm/jdk1.8.0_40/bin/java 300
>> sudo update-alternatives --install /usr/bin/javac javac /usr/lib/jvm/jdk1.8.0_40/bin/javac 300
>> sudo update-alternatives --config java
>> sudo update-alternatives --config javac

7、查看版本

>> java -version
>> javac -version