Python中xml初始数据已及csv文件和多线程

项目的研发或者上线阶段,为了方便,可能需要初始化数据库:包括用户,权限,或者一些其他的基础数据。我这里采用的是解析Xml文件初始化数据库。

 

(1)Xml文件的格式如下:

 Python中xml初始数据已及csv文件和多线程

 

(2)配置初始化数据的Servlet

     在web.xml中配置

     <servlet>

<servlet-name>PersistenceTest</servlet-name>

<servlet-class>com.saving.ecm.servlet.PersistenceInitialize</servlet-class>

<load-on-startup>2</load-on-startup>

 </servlet>

 

(3)Tomcat服务器启动时,加载Servlet

    public class PersistenceInitialize extends HttpServlet {

private static final long serialVersionUID = 1L;

private static final String FILEPATH = "initDataBase.xml";

 

@Override

public void init() throws ServletException {

super.init();

try {

           //如果用户数据count = 0

           Document document = new 

SAXReader().read(Thread.currentThread().getContextClassLoader()

.getResourceAsStream(FILEPATH));

   initUser(document);// 初始化用户

} catch (Throwable e) {

e.printStackTrace();

}

}

 

@SuppressWarnings("unchecked")

private void initUser(Document document) {

List<Node> childNodes = document.selectNodes("//users/user");

CommonAction<User> action = new CommonAction<User>(User.class);

for (Node node : childNodes) {

User user;

try {

user = action.findById(Long.parseLong(node.valueOf("@id")));

if (user == null) {

user = new User();

 

}

user.setAccount(node.valueOf("@account"));

user.setName(node.valueOf("@name"));

user.setPassword(MD5Util.md5(node.valueOf("@password")));

user.setEmail(node.valueOf("@email"));

user.setRoleCode(node.valueOf("@roleCode"));

user.setStatus(node.valueOf("@status"));

user.setCreationTime(System.currentTimeMillis());

action.saveEntity(user);

 

} catch (Throwable e) {

e.printStackTrace();

}

 

}

}

 

}

 csv文件

逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)。纯文本意味着该文件是一个字符序列,不含必须像二进制数字那样被解读的数据。CSV文件由任意数目的记录组成,记录间以某种换行符分隔;每条记录由字段组成,字段间的分隔符是其它字符或字符串,最常见的是逗号或制表符。通常,所有记录都有完全相同的字段序列。通常都是纯文本文件。建议使用WORDPAD或是记事本(NOTE)来开启,再则先另存新档后用EXCEL开启,也是方法之一。
CSV文件格式的通用标准并不存在,但是在RFC 4180中有基础性的描述。使用的字符编码同样没有被指定,但是7-bitASCII是最基本的通用编码。

用法

编辑
CSV是一种通用的、相对简单的文件格式,被用户、商业和科学广泛应用。最广泛的应用是在程序之间转移表格数据,而这些程序本身是在不兼容的格式上进行操作的(往往是私有的和/或无规范的格式)。因为大量程序都支持某种CSV变体,至少是作为一种可选择的输入/输出格式。
例如,一个用户可能需要交换信息,从一个以私有格式存储数据的数据库程序,到一个数据格式完全不同的电子表格。最可能的情况是,该数据库程序可以导出数据为“CSV”,然后被导出的CSV文件可以被电子表格程序导入。
“CSV”并不是一种单一的、定义明确的格式(尽管RFC 4180有一个被通常使用的定义)。因此在实践中,术语“CSV”泛指具有以下特征的任何文件:
  1. 纯文本,使用某个字符集,比如ASCIIUnicodeEBCDICGB2312
  2. 由记录组成(典型的是每行一条记录);
  3. 每条记录被分隔符分隔为字段(典型分隔符有逗号、分号或制表符;有时分隔符可以包括可选的空格);
  4. 每条记录都有同样的字段序列。
在这些常规的约束条件下,存在着许多CSV变体,故CSV文件并不完全互通。然而,这些变异非常小,并且有许多应用程序允许用户预览文件(这是可行的,因为它是纯文本),然后指定分隔符、转义规则等。如果一个特定CSV文件的变异过大,超出了特定接收程序的支持范围,那么可行的做法往往是人工检查并编辑文件,或通过简单的程序来修复问题。因此在实践中,CSV文件还是非常方便的。

规则

编辑
1 开头是不留空,以行为单位。
2 可含或不含列名,含列名则居文件第一行。
3 一行数据不跨行,无空行。
4 以半角逗号(即,)作分隔符,列为空也要表达其存在。
5列内容如存在半角引号(即"),替换成半角双引号("")转义,即用半角引号(即"")将该字段值包含起来。
6文件读写时引号,逗号操作规则互逆。
7内码格式不限,可为 ASCII、Unicode 或者其他。
8不支持数字
8不支持特殊字符

import csv     # 需要import csv的文件包

out=open("aa.csv",'wb')         # 注意这里如果以‘w’的形式打开,每次写入的数据中间就会多一个空行,所以要用‘wb’

csv_write=csv.write(out,dialect='excel')

                                              # 下面进行具体的内容写入

ss=['a',3]

csv_write.writerow(ss)      #这样ss里面的信息就被写入到aa.csv文件中了,而且是在两列中

                                     #这里如果需要写入多行,那么就采用循环进行循环输入就可以啦哈

out.close()


2.读取CSV文件

import csv

out=open("aa.csv",'r')

read_csv=csv.reader(out,dialect='excel')

for line in read_csv:     #循环输出csv中的所有数据

    print line

out.close()


线程

Python中创建线程有两种方式:函数或者用类来创建线程对象。

  • 函数式:调用 _thread 模块中的start_new_thread()函数来产生新线程。
  • 类:创建threading.Thread的子类来包装一个线程对象。

一.函数式:调用thread模块中的start_new_thread()函数来产生新线程

thread.start_new_thread ( function, args[, kwargs] )
  • function - 线程函数
  • args - 传递给线程函数的参数,他必须是个tuple类型
  • kwargs - 可选参数

例:通过thread来创建新线程

Python中xml初始数据已及csv文件和多线程
import thread,time

def timer(name,delay):
    count = 0
    while count < 5:
        time.sleep(delay)
        count +=1
        print "%s:%s" %(name,time.ctime())

#创建两个线程
thread.start_new_thread(timer,('Thread-1',2,))   #timer表示执行timer函数,后面元组内表示timer函数的两个参数
thread.start_new_thread(timer,('Thread-2',4,))
while 1:
    pass
Python中xml初始数据已及csv文件和多线程

 输出结果:

Python中xml初始数据已及csv文件和多线程
Thread-1:Tue Oct 18 16:05:23 2016
Thread-1:Tue Oct 18 16:05:25 2016
Thread-2:Tue Oct 18 16:05:25 2016
Thread-1:Tue Oct 18 16:05:27 2016
Thread-1:Tue Oct 18 16:05:29 2016
Thread-2:Tue Oct 18 16:05:29 2016
Thread-1:Tue Oct 18 16:05:31 2016
Thread-2:Tue Oct 18 16:05:33 2016
Thread-2:Tue Oct 18 16:05:37 2016
Thread-2:Tue Oct 18 16:05:41 2016
Python中xml初始数据已及csv文件和多线程

 

二.类:创建threading.Thread的子类来包装一个线程对象

例1,通过threading来创建新线程:

Python中xml初始数据已及csv文件和多线程
import threading,time

def show(arg):
    time.sleep(2)
    print 'thread' + str(arg)

for i in range(10):
    t = threading.Thread(target=show,args=(i,))  #target=show执行show函数,后面args表示show函数中传入的参数
    t.start()
Python中xml初始数据已及csv文件和多线程

运行结果:

Python中xml初始数据已及csv文件和多线程
Main thread stop.
Tue Oct 18 11:44:41 2016
thread0
thread2
thread4
thread3
thread1
thread8
thread6
thread5
thread7
thread9
Python中xml初始数据已及csv文件和多线程

 

例2:单线程

Python中xml初始数据已及csv文件和多线程
from time import ctime,sleep
def Music(music):
    for i in range(2):
        print ('I am listening to the music now...%s' %ctime())
        sleep(2)

def Movie(movie):
    for i in range(2):
        print('I am watching movie now...%s' %ctime())
        sleep(5)

if __name__ == '__main__':
    Music('Goodbye')
    Movie('Who Am I')
    print ('Main Process is over...%s' %ctime())
Python中xml初始数据已及csv文件和多线程

输出结果:

I am listening to the music now...Mon Dec 12 14:53:24 2016
I am listening to the music now...Mon Dec 12 14:53:26 2016
I am watching movie now...Mon Dec 12 14:53:28 2016
I am watching movie now...Mon Dec 12 14:53:33 2016
Main Process is over...Mon Dec 12 14:53:38 2016

 

例3:多线程

Python中xml初始数据已及csv文件和多线程
import threading
import time

def Music(music):
    for i in range(2):
        print('I am listening to the <%s> now...%s' %(music,time.ctime()))
        time.sleep(2)

def Movie(movie):
    for i in range(2):
        print('I am watching <%s> now...%s' %(movie,time.ctime()))
        time.sleep(5)

t1 = threading.Thread(target=Music,args=('I Will',))
t2 = threading.Thread(target=Movie,args=('The Walking Dead',))

if __name__ == '__main__':
    #t1.daemon = True   #如果为True,说明该线程为守护线程,也就表明这个线程不重要,在主线程退出的时候不用等待这个线程
    #t2.daemon = True
    #如果想等待子线程执行完之后,主线程才退出,就不需要设置daemon属性(daemon属性默认就为False)
    t1.start()
    t2.start()
    #t1.join()    #停止主线程,直到执行完子线程t1后才执行主线程
    #t2.join()    #停止主线程,直到执行完子线程t2后才执行主线程
    print('all is over...%s' %time.ctime())
Python中xml初始数据已及csv文件和多线程

输出结果:

I am listening to the <I Will> now...Mon Dec 12 14:41:48 2016   #与另外一条子线程同时运行的,注意时间!
I am watching <The Walking Dead> now...Mon Dec 12 14:41:48 2016
all is over...Mon Dec 12 14:41:48 2016
I am listening to the <I Will> now...Mon Dec 12 14:41:50 2016
I am watching <The Walking Dead> now...Mon Dec 12 14:41:53 2016

上面例题中如果启用t1.join和t2.join结果如下:

I am listening to the <I Will> now...Mon Dec 12 14:42:56 2016
I am watching <The Walking Dead> now...Mon Dec 12 14:42:56 2016
I am listening to the <I Will> now...Mon Dec 12 14:42:58 2016
I am watching <The Walking Dead> now...Mon Dec 12 14:43:01 2016
all is over...Mon Dec 12 14:43:06 2016    #等待子线程运行结束后才执行主线程

 

Threading模块中所有对象:

1,Thread

Python中xml初始数据已及csv文件和多线程
  • start() #开始线程的执行
  • run() #定义线程的功能的函数(一般会被子类重写)
  • join(timeout=None) #程序挂起,直到该线程执行结束(如果设置了timeout,最多阻塞timeout秒)
  • getName() #返回线程名字
  • setName(name) #设置线程名字
  • isAlive() #查看该线程是否还在运行
  • isDaemon(False) #设置守护进程(True)或非守护线程(默认为False),如果设置为守护线程(True)表示该线程不重要,主线程无需等待该线程结束才退出。
Python中xml初始数据已及csv文件和多线程

2,Lock(Rlock):只允许一个线程更改数据。提供acquire方法(获取锁)和release方法(释放锁)

  • RLock和Lock 的区别:RLock允许在同一线程中被多次acquire和release。RLock中acquire和release必须成对出现,即调用了n次acquire,必须调用n次的release才能真正释放所占用的琐。而Lock不一样,同一线程只能使用一次acquire和release方法。

3,condition

4,Event

5,Semaphore(BoundedSemaphore):同时允许一定数量的线程更改数据,信号量也提供acquire方法和release方法。

6,其他函数:

activeCount() #返回当前活动线程的数量
currentThread() #返回当前线程
enumerate() #返回当前活动线程的列表
settrace(func) #为所有线程设置一个跟踪函数
setprofile() #为所有线程设置一个profile函数

 

多线程实现同步的方法:

1.线程锁:在同一个进程中的资源,所有线程都是共享的。线程之间是进行随机调度,如果不同线程同时对数据进行修改,就会产生问题。为了保证数据的准确性,引入了锁的概念。也就是在同一时刻只允许一个线程操作该数据。

锁有两种状态:锁定和未锁定

每当一个线程1要访问共享数据时,必须先获得锁定;如果已经有别的线程2获得锁定了,那么就让线程1暂停,也就是同步阻塞;等到线程2访问完毕,释放锁以后,再让线程1继续。

使用锁方法:

lock = threading.Lock()   #创建锁
lock.acquire([timeout])   #锁定 
lock.release()   #释放 

例1:未使用锁之前:(注意同一时间点,num值的变化)

Python中xml初始数据已及csv文件和多线程
import threading
import time

num = 0

def fun(arg):
    global num
    time.sleep(1)
    num += 1
    print(num,'-->','%s'%time.ctime())

for item in range(5):  #开启5个子线程
    t = threading.Thread(target=fun,args=(item,))
    t.start()

print('Main threading stop !')
Python中xml初始数据已及csv文件和多线程

输出结果:

Python中xml初始数据已及csv文件和多线程
Main threading stop !
1 --> Mon Dec 12 15:51:03 2016
2 --> Mon Dec 12 15:51:03 2016
3 --> Mon Dec 12 15:51:03 2016   #同一时间点输出的num都不一样
4 --> Mon Dec 12 15:51:03 2016
5 --> Mon Dec 12 15:51:03 2016
Python中xml初始数据已及csv文件和多线程

 

例2:使用锁之后:

Python中xml初始数据已及csv文件和多线程
import threading
import time

num = 0
lock = threading.Lock()    #创建锁

def fun(arg):
    lock.acquire()   #获取锁
    global num
    time.sleep(1)
    num += 1
    print(num,'-->','%s'%time.ctime())
    lock.release()   #释放锁


for item in range(5):  #开启5个子线程
    t = threading.Thread(target=fun,args=(item,))
    t.start()

print('Main threading stop !')
Python中xml初始数据已及csv文件和多线程

输出结果:

Python中xml初始数据已及csv文件和多线程
Main threading stop !
1 --> Mon Dec 12 15:56:34 2016
2 --> Mon Dec 12 15:56:35 2016
3 --> Mon Dec 12 15:56:36 2016    #注意:同一时间点num值不变
4 --> Mon Dec 12 15:56:37 2016
5 --> Mon Dec 12 15:56:38 2016
Python中xml初始数据已及csv文件和多线程

 

2,信号量Semaphore

例:

Python中xml初始数据已及csv文件和多线程
import threading
import time

se = threading.Semaphore(5)  #同时允许5个线程修改数据

def fun(n):
    se.acquire()
    time.sleep(1)
    print('thread:%s -->%s'%(n,time.ctime()))
    se.release()

if __name__ == '__main__':
    for i in range(10):
        t = threading.Thread(target=fun,args=(i,))
        t.start()
Python中xml初始数据已及csv文件和多线程

输出结果:

Python中xml初始数据已及csv文件和多线程
thread:0 -->Mon Dec 12 16:36:12 2016
thread:1 -->Mon Dec 12 16:36:12 2016
thread:3 -->Mon Dec 12 16:36:12 2016
thread:2 -->Mon Dec 12 16:36:12 2016
thread:4 -->Mon Dec 12 16:36:12 2016   #同一时间点,允许5个线程同时修改值
thread:6 -->Mon Dec 12 16:36:13 2016
thread:8 -->Mon Dec 12 16:36:13 2016
thread:5 -->Mon Dec 12 16:36:13 2016
thread:9 -->Mon Dec 12 16:36:13 2016
thread:7 -->Mon Dec 12 16:36:13 2016
Python中xml初始数据已及csv文件和多线程

3,时间event:通用的条件变量,多个线程可以等待某个事件发生后,所有线程都被**。事件主要提供了三个方法 set、wait、clear。

事件处理的机制:

全局定义了一个“Flag”:
(1)如果“Flag”值为 False,那么当程序执行 event.wait 方法时就会阻塞
(2)如果“Flag”值为True,那么event.wait 方法时便不再阻塞

clear:将“Flag”设置为False
set:将“Flag”设置为True

Python中xml初始数据已及csv文件和多线程
import threading

eve = threading.Event()

def fun(e):
    print('start...')
    e.wait()
    print('execute...')

for i in range(5):
    t = threading.Thread(target=fun,args=(eve,))
    t.start()

eve.clear()
usr_input = input('Enter the flag:')
if usr_input =='1':
    eve.set()
Python中xml初始数据已及csv文件和多线程

输出结果:

Python中xml初始数据已及csv文件和多线程
start...
start...
start...
start...
start...
Enter the flag:1
execute...
execute...
execute...
execute...
execute...
Python中xml初始数据已及csv文件和多线程

 

4,条件Condition:使线程进入等待状态,当满足某个条件时,才释放线程。

notify()方法会唤醒一个在等待conditon变量的线程;notify_all() 则会唤醒所有在等待conditon变量的线程

例如生产者模型:

Python中xml初始数据已及csv文件和多线程
import threading
import time
c = threading.Condition()

def fun(n):
    c.acquire()
    c.wait()
    print('current threading:%s ---> %s' %(n,time.ctime()))
    time.sleep(1)
    c.release()

if __name__ == '__main__':
    for i in range(10):
        t = threading.Thread(target=fun,args=(i,))
        t.start()

    while True:
        usr_input = input('Enter:')
        if usr_input == 'q':
            break

        c.acquire()
        c.notify(int(usr_input))
        c.release()
Python中xml初始数据已及csv文件和多线程

输出结果:

Python中xml初始数据已及csv文件和多线程
Enter:3
current threading:1 ---> Mon Dec 12 17:14:40 2016
current threading:2 ---> Mon Dec 12 17:14:41 2016
current threading:0 ---> Mon Dec 12 17:14:39 2016
current threading:0 ---> Mon Dec 12 17:14:39 2016
Enter:5
current threading:4 ---> Mon Dec 12 17:14:47 2016
current threading:6 ---> Mon Dec 12 17:14:48 2016
current threading:3 ---> Mon Dec 12 17:14:49 2016
current threading:5 ---> Mon Dec 12 17:14:50 2016
current threading:7 ---> Mon Dec 12 17:14:51 2016
Enter:3
current threading:9 ---> Mon Dec 12 17:14:59 2016
current threading:8 ---> Mon Dec 12 17:15:00 2016
Enter:q

Process finished with exit code 0
Python中xml初始数据已及csv文件和多线程

 

5.定时器:指定n秒后执行某操作

Python中xml初始数据已及csv文件和多线程
import threading
import time

print('Time:%s'%time.ctime())
def Print():
    print('hello,python...%s'%time.ctime())

t = threading.Timer(2,Print)   #2秒后执行Print函数
t.start()
Python中xml初始数据已及csv文件和多线程

输出结果:

Time:Mon Dec 12 17:24:50 2016
hello,python...Mon Dec 12 17:24:52 2016  #2秒后执行

 

同步队列Queue:

  • Queue模块提供了同步队列和线程安全。包括FIFO队列、LIFO队列以及优先级队列。可以使用队列来实现线程间的同步。

    FIFO:(默认为FIFO)

  • Queue模块可以用来进行线程间通讯,让各个线程之间共享数据。
  • Queue解决了生产者,消费者的问题。

Queue模块常用方法:

Python中xml初始数据已及csv文件和多线程
import queue  #导入queue模块
q = queue.Queue(maxsize=0)   #构造一个FIFO队列。maxsize指定队列的长度。为0时,表示队列长度无限制。

q.put(item='n',block=1,timeout=None)   #在队尾插入一个item(必选项)。如果当前队列为空,且block为1(默认值)时,put()方法就使
#线程暂停,一直阻塞到队列中有空间为止;如果block为0,put()方法会引发Full异常。

q.get(block=1,timeout=None)   #从队首删除并返回一个项目。当block为1(默认值)时,get()方法使线程暂停,直到有项目可用。如果队列为空,且block为0时,队列将引发empty异常。

q.put_nowait(item='n')   #相当于q.put(item,False)
q.get_nowait()   #相当于q.get(False)
q.join()  #等到队列为空时,在执行别的操作
q.qsize()  #返回队列的大小
q.empty()  #当队列为空时,返回True,否则返回False
q.full()  #当队列满时,返回True,否则返回False
q.task_done()   #在完成一项工作之后,它向任务已完成的队列发送一个信号
Python中xml初始数据已及csv文件和多线程

例:

Python中xml初始数据已及csv文件和多线程
from threading import Thread
from queue import Queue
import time

class Producer(Thread):   #定义生产者类
    def __init__(self,name,queue):
        self.Name = name
        self.Queue = queue
        super(Producer,self).__init__()   #执行父类的构造函数

    def run(self):     #生产者具体工作内容
        while True:
            if self.Queue.full():
                time.sleep(1)
            else:
                self.Queue.put('产品')
                time.sleep(1)
                print ('%s生产一个产品' %(self.Name,))

                #Thread.run(self)

class Consumer(Thread):   #定义消费者类
    def __init__(self,name,queue):
        self.Name = name
        self.Queue = queue
        super(Consumer, self).__init__()   #执行父类的构造函数
    def run(self):
        while True:
            if self.Queue.empty():
                time.sleep(1)
            else:
                self.Queue.get('产品')
                time.sleep(1)
                print ('%s消费了一个产品' %(self.Name,))
                #Thread.run(self)

que = Queue(maxsize=100)   #定义容器

person1 = Producer('P1',que)   #创建生产者P1
person1.start()
person2 = Producer('P2',que)   #创建生产者P2
person2.start()
person3 = Producer('P3',que)   #创建生产者P3
person3.start()

for num in range(20):   #创建消费者20人:C1,C2...C20
    name = 'C1%d' %(num,)
    item = Consumer(name,que)
    item.start()
总结
xml初始化

    

XML 初始化用于创建新的 Internet 语言

很多新的 Internet 语言是通过 XML 创建的:

其中的例子包括:

  • XHTML - 最新的 HTML 版本
  • WSDL - 用于描述可用的 web service
  • WAP 和 WML - 用于手持设备的标记语言
  • RSS - 用于 RSS feed 的语言
  • RDF 和 OWL - 用于描述资源和本体

  • SMIL - 用于描述针针对 web 的多媒体


CSV文件作用

CSV逗号分隔值文件(Comma Separated value),是一种用来存储数据的纯文本文件格式,通常用于电子表格或数据库软件。 
东芝CSV超显亮技术(Clear Super View),是东芝独家专利技术。
CSV昂贵国家鉴定(Costly State Verification),在合同理论中,考虑到合同设计在核实(或公布)公司行为的问题上花费很高的成本,借款者不得不支付监控成本。
CSV最常见于图片扫描文件包中,以下为这种用途文件的介绍。
COMMA SEPARATED VALUE的缩写,出现在档案总管中的档案类型是「逗号分隔」,依计算机原来的设定,如果直接点选该档案,计算机将以EXCEL的模式开启该档案。但建议您千万不要这么做,因为CSV档如果以EXCEL开启,由于计算机档案数据转换的原因,会将其CRC之数值改做科学记号方式储存,而造成档案中的 CRC值发生错误。这也是笔者初出茅庐时所得到的惨痛经验,但如果想一窥CSV档的真实面貌,笔者建议您使用WORDPAD或是记事本(NOTE)来开启,再则先另存新档后用EXCEL开启,也是方法之一。开启后的CSV档包含了四或五个字段(部分),由左至右分别记载着:文件名称(XXXX.JPG)、档案大小(以BYTE为单位)、CRC32值(八个英文字母或数字组成)、档案路径(档案储存的子目录名称)和档案内容描述(一般来说都是明星的英文姓名甚或是专辑名称,也可能空白)。而其中第四栏「档案路径」因为每个人储存整理图档的方式不同,所以本栏通常不存在,而一般有含有「档案路径」这栏的CSV档,又称为ECSV档案

多线程

Python多线程有缺陷,总被人说成是鸡肋,但也不是一无用处,它很适合用在IO密集型任务中。I/O密集型执行期间大部分是时间都用在I/O上,如数据库I/O,较少时间用在CPU计算上。因此该应用场景可以使用Python多线程,当一个任务阻塞在IO操作上时,我们可以立即切换执行其他线程上执行其他IO操作请求。

Python多线程在IO密集型任务中还是很有用处的,而对于计算密集型任务,应该使用Python多进程