Python os.walk() 方法
os.walk() 方法用于通过在目录树中游走输出在目录中的文件名,向上或者向下。os.walk() 方法是一个简单易用的文件、目录遍历器,可以帮助我们高效的处理文件、目录方面的事情。在Unix,Windows中有效。 语法 walk()方法语法格式如下: os.walk(top[, topdown=True[, one rror=None[, followlinks=False]]]) 参数 top -- 是你所要遍历的目录的地址, 返回的是一个三元组(root,dirs,files)。topdown --可选,为 True,则优先遍历 top 目录,否则优先遍历 top 的子目录(默认为开启)。如果 topdown 参数为 True,walk 会遍历top文件夹,与top 文件夹中每一个子目录。 root 所指的是当前正在遍历的这个文件夹的本身的地址 dirs 是一个 list ,内容是该文件夹中所有的目录的名字(不包括子目录) files 同样是 list , 内容是该文件夹中所有的文件(不包括子目录) onerror -- 可选,需要一个 callable 对象,当 walk 需要异常时,会调用。 followlinks -- 可选,如果为 True,则会遍历目录下的快捷方式(linux 下是软连接 symbolic link )实际所指的目录(默认关闭),如果为 False,则优先遍历 top 的子目录。 返回值 返回生成器。 使用:-遍历文件和便利文件夹 def walkFile(file): for root, dirs, files in os.
MySQL微讲解(四) 查询关键字 1.having过滤 having与where的功能一模一样,都是对数据进行筛选,where是用在分组之前,having用在分组之后,为了区分两者,我们将where说为筛选,having称之为过滤 # 统计每个部门年龄在30岁以上的员工的平均薪资,并且保留平均薪资大于10000的部门 1.先获取每个部门年龄在30岁以上的员工的平均薪资 select post,avg(salary) from emp where age > 30 group by post; 2.在第一步的基础上过滤出平均薪资大于10000的数据 select post,avg(salary) from emp where age > 30 group by post having avg(salary) > 10000; # 针对聚合函数,如果还需要在其他地方继续作为条件使用的可以先使用别名 select post,avg(salary) as avg_salary from emp where age > 30 group by post having avg_salary > 10000; 2.distinct去重 # 去重的前提是数据必须一模一样才可以,如果数据有主键肯定无法去重 select distinct age from emp; # 对年龄数据进行去重 3.order by排序 # 1.薪资按照高低排序 select * from emp order by salary; # 默认是升序 select * from emp order by salary asc; # 升序的关键字,也可以不写 select * from emp order by salary desc; # 降序的关键字 # 2.
在游戏服务器当中,通常都会为每个客户端链接设置一个缓冲区。这样做的理由是游戏中通常会有持续不断,零碎的数据包发送到客户端,使用一个缓冲区可以把这些数据包攒到一起发送,避免频繁的io操作;另一个原因是,处理游戏逻辑的线程通常和io操作的线程是分开的,因此游戏逻辑线程把数据放到缓冲区后可以继续处理后续的逻辑,数据的收发交给io线程。
我自己设计的服务器,在早期的版本中,Socket的缓冲区是采用了一个大小可变缓冲区。即每个Socket创建时,需要上层逻辑根据Socket的类型指定缓冲区的上限,例如客户端Socket上限为64kb,服务器与服务器之间的上限为64M。然后给socket初始化一个8kb的缓冲区,当缓冲区满并且未达到上限时,通过memcpy切换到一个更大的缓冲区,如16kb,接着是32kb,64kb...,只增不减,直到达到上限。这样设计的优点是收(recv)、发(send),还是(通过protobuf)解析数据包,,由于永远只有一个缓冲区,数据在内存上是连续的,那这些操作都可以一次完成。缺点也十分明显,这缓冲区是可变的,意味着我需要设计一个大小可变的内存池,类似于boost的ordered_malloc和ordered_free,并且由于只增不减,浪费的内存也相对严重。
在后续版本的优化当中,我认为针对游戏服务器而言,一个健康的服务器socket的缓冲区中不应该有太多的数据。即可以在Socket中缓存64M的数据,但对于游戏服务器而言,单个请求数据量往往很小,64M数据意味着上百万个请求被阻塞,这服务器已经卡到可以关服了,没什么意义了。因此我决定改掉这个复杂又浪费内存单个缓冲区设计,转而采用典型的链表结构,即缓冲区1-->缓冲区2-->缓冲区3-->null。第一个缓冲区满,再申请一个同样大小新的缓冲区链到链表尾部,当缓冲区用完时,依次释放到内存池。这种设计缓冲区的大小是固定的,设计简单可靠,通过调整单个缓冲区的大小,可以大大地提高缓冲区利用率。而随之而来的缺点是由于数据在内存上不是连续的,收(recv)、发(send)只能分多次进行,(通过protobuf)解析数据包时,由于数据不连续,需要把数据拷贝到一个足够大,连续的缓冲区才能进行解析。不过这些缺点只要单个缓冲区的大小配置得当,都是极少出现的,因此是可以接受的。
优化完成后,重新进行了测试,测试的方式也很简单
客户端每秒发送一个ping数据包(里面包含一个巨大的随机字符串) --- 服务器网关进程收到数据包 --- 网关进程向其他进程(AREA1、AREA2、WORLD)发起ping | | ▼ 客户端收到ping返回,校验字符串是否完整,并校验延迟是否在预期范围 <<<--- 服务器网关进程返回数据包 <<<--- 网关进程收到其他进程(AREA1、AREA2、WORLD)返回的ping数据包,并记录延迟 测试结果表示字符串是完整的,说明缓冲区的设计基本没有问题。但发现了一个令我十分不解的问题,那就是延迟实在是太大了。
[A1LP05-06 22:03:28]ping android_65537 29 1 42225 [A1LP05-06 22:03:30]ping android_65537 30 85 19149 [A1LP05-06 22:03:30] latency too large AREA(I2.S1) 85 [A1LP05-06 22:03:30] latency too large AREA(I1.S1) 85 [A1LP05-06 22:03:30] latency too large WORLD(I1.S1) 85 [A1LP05-06 22:03:30]ping android_65537 31 0 47831 [A1LP05-06 22:03:31]ping android_65537 32 42 8181 [A1LP05-06 22:03:31] latency too large AREA(I2.S1) 42 [A1LP05-06 22:03:31] latency too large AREA(I1.
绝对路径的三种写法:
方法1,
with open(rC:\Git\moxyrulesnewui_python\org\adv\rules\UIAutomation\testcase\test.py) as file_obj:
contents = file_obj.read()
print(contents.strip)
方法2,
with open(C:\\Git\\moxyrulesnewui_python1\\org\\adv\\rules\\UIAutomation\\testcase\\test.py) as file_obj:
contents = file_obj.read()
print(contents.strip)
方法3
with open(C:/Git/moxyrulesnewui_python/org/adv/rules/UIAutomation/testcase/test.py) as file_obj:
contents = file_obj.read()
print(contents.strip)
相对路径:
import os
import sys
BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__File__)))
sys.path.insert(0, BASE_DIR)
with open(test.py) as file_obj:
contents = file_obj.read()
print(contents.strip)
利用以上四种方法可以解决错误: FileNotFoundError: [Errno 2] No such file or directory,ModuleNotFoundError: No module named xxx
一、IF(expr1,expr2,expr3): 如果expr1为TRUE,则IF()返回值为expr2,否则返回值为expr3
二、IFNULL(expr1,expr2): 假如expr1不为null,则返回expr1,否则返回expr2
三:IF…ELSE…语句 1 IF search_condition THEN 2 statement_list 3 ELSE 4 statement_list 5 END IF; earch_condition表示条件,如果成立时执行THEN后面的statement_list语句,否则执行ELSE后面的statement_list语句。search_condition是一个条件表达式,可以由条件运算符组成,也可以使用AND、OR、NOT对多个表达式进行组合
1. substring_index(str,delim,count)
str 表示要处理的字符串
delim 表示分隔符
count 计数
select substring_index(us.profile,',',-1) as gender,
count(*) as number
from user_submit us
group by gender;
比较count(*)和count(字段名)的区别:
前者对行的数目进行计算,包含null,
后者对特定的列的值具有的行数进行计算,不包含null,得到的结果将是除去值为null和重复数据后的结果。
2.
select difficult_level, (sum(case when qpd.result = right then 1 else 0 end)/count(u.answer_cnt)) as correct_rate from user_profile u inner join question_practice_detail qpd on u.device_id = qpd.device_id inner join question_detail qd on qd.question_id = qpd.
NIS:网络信息服务 Linux系统中用户按地域分两类:本地用户,远程用户(NIS、LDAP、AD)模式:C/S模式ypbind是定义NIS服务器的客户端进程,一旦确定了服务器位置,客户端绑定到了服务器上,所有客户的查询都发往NIS服务器。ypserv是回答客户端查询的服务器进程。 一、安装NIS服务器(Server端192.168.2.21)设置主机名 hostnamectl set-hostname david 设置完后可以用hostname确认关闭防火墙和防火墙的开机启动 systemctl stop firewalld systemctl disable firewalld.service 1、安装软件包 yp-tools yum install ypserv ypbind nfs-utils rpcbind 2、设置NIS域名 nisdomainname testserver.com 如果不想每次重启都设置则需要修改network文件 vim /etc/sysconfig/network 添加一行NISDOMAIN=testserver.com 设置开机自动加入NIS域 vim /etc/rc.d/rc.local 添加一行/bin/nisdomainname testserver.com 3、修改配置文件在/etc/hosts末尾加上 192.168.2.21 david 192.168.2.25 client 修改/etc/ypserv.conf把最后一行的注释去掉,也就是说通配所有的主机,加入所有的域,map所有的东西,none是表示没有安全性,这一项其实是个安全选项,可以通过这个控制权限 * : * : * : none 为了安全,你可以这样写: 127.0.0.0/255.255.255.0 : * : * : none 192.168.2.0/255.255.255.0 : * : * : none * : * : * : deny 4、启动NIS服务 systemctl start rpcbind (service rpcbind start) systemctl start yppasswdd systemctl start ypserv 5、在home下新建目录nis_users(用于nfs共享)然后新增用户user1,user2并指定home目录和设置密码 mkdir /home/nis_users useradd -d /home/nis_users/user1 user1 6、初始化数据库 /usr/lib64/yp/ypinit -m 按Ctrl + D,再按y确认//每次更新账户信息后都需要更新数据库 //cd /var/yp 再 make 或者 //make -C /var/yp/ 现在执行下面的命令,并可以看到用户口令表 getent passwd 7、通过NFS共享/home/nis_users目录(i)、首先禁用selinux vim /etc/selinux/config 将SELINUX=enforcing改为:SELINUX=disabled,保存退出。输入setenforce 0立即生效(ii)、vim /etc/exports添加一行,格式为共享目录 网络地址 (rw, sync) /home/nis_users 192.
前言 并发编程是一项非常重要的技术,无论在面试,还是工作中出现的频率非常高。
之前我发表的一篇《聊聊并发编程的10个坑》,在全网广受好评。说明了这类文章还是比较有价值的,接下来,打算继续聊聊并发编程这个话题。
并发编程说白了就是多线程编程,但多线程一定比单线程效率更高?
答:不一定,要看具体业务场景。
毕竟如果使用了多线程,那么线程之间的竞争和抢占cpu资源,线程的上下文切换,也是相对来说比较耗时的操作。
下面这几个问题在面试中,你必定遇到过:
你在哪来业务场景中使用过多线程? 怎么用的? 踩过哪些坑? 今天聊聊我之前在项目中用并发编程的12种业务场景,给有需要的朋友一个参考。
1. 简单定时任务 各位亲爱的朋友,你没看错,Thread类真的能做定时任务。如果你看过一些定时任务框架的源码,你最后会发现,它们的底层也会使用Thread类。
实现这种定时任务的具体代码如下:
public static void init() { new Thread(() -> { while (true) { try { System.out.println(下载文件); Thread.sleep(1000 * 60 * 5); } catch (Exception e) { log.error(e); } } }).start(); } 使用Thread类可以做最简单的定时任务,在run方法中有个while的死循环(当然还有其他方式),执行我们自己的任务。有个需要特别注意的地方是,需要用try...catch捕获异常,否则如果出现异常,就直接退出循环,下次将无法继续执行了。
但这种方式做的定时任务,只能周期性执行,不能支持定时在某个时间点执行。
特别提醒一下,该线程建议定义成守护线程,可以通过setDaemon方法设置,让它在后台默默执行就好。
使用场景:比如项目中有时需要每隔5分钟去下载某个文件,或者每隔10分钟去读取模板文件生成静态html页面等等,一些简单的周期性任务场景。
使用Thread类做定时任务的优缺点:
优点:这种定时任务非常简单,学习成本低,容易入手,对于那些简单的周期性任务,是个不错的选择。
缺点:不支持指定某个时间点执行任务,不支持延迟执行等操作,功能过于单一,无法应对一些较为复杂的场景。
2.监听器 有时候,我们需要写个监听器,去监听某些数据的变化。
比如:我们在使用canal的时候,需要监听binlog的变化,能够及时把数据库中的数据,同步到另外一个业务数据库中。
如果直接写一个监听器去监听数据就太没意思了,我们想实现这样一个功能:在配置中心有个开关,配置监听器是否开启,如果开启了使用单线程异步执行。
主要代码如下:
@Service public CanalService { private volatile boolean running = false; private Thread thread; @Autowired private CanalConnector canalConnector; public void handle() { //连接canal while(running) { //业务处理 } } public void start() { thread = new Thread(this::handle, name); running = true; thread.
根据经纬度坐标获得省市区县行政区划城市名称,自建数据库 java python php c# .net 均适用 目录 步骤一、下载省市区边界数据 步骤二、解析CSV文件导入数据库 步骤三、在程序中根据坐标解析获得城市 在LBS应用中,根据坐标来解析获得对应是哪个城市是一个很常见的功能,比如App里面通过手机定位自动选择城市;本文介绍的是通过自己建的数据库,利用SQL空间查询来进行坐标解析得到对应的省市区,绝大部分支持空间数据类型(Spatial)的数据库均支持,包括但不限于:MySQL、SQL Server、Oracle、PostgreSQL等;开发语言不限,只要能进行数据库查询就都支持,用Java、Python、PHP、C#均能很简单的实现。
省市区边界数据在线预览、下载:https://xiangyuecn.gitee.io/areacity-jsspider-statsgov/GitHub地址:https://github.com/xiangyuecn/AreaCity-JsSpider-StatsGov
通过坐标来获取地址:百度地图提供的接口叫 “地址逆解析”,高德地图提供的接口叫 “地理逆编码”,它们开放平台均提供了前后端接口,发个http请求就可以拿到数据,相关的接口调用请自行阅读平台开发文档,使用起来很方便。
当然这篇文章不会去介绍怎么搞街道门牌号这些完整地址,也不讲怎么样调用人家的接口,只介绍坐标对应的省市区名称的获取,自建数据库写SQL进行空间查询,完全自己实现,比调开放平台接口相对会复杂些。
由于全国区县每年都会有比较多的变更,所以省市区边界数据需要经常去同步维护,好在这上面这个开源库有在持续的长期维护,新数据发布后更新相对容易很多。由于开源库更新维护数据比较及时,所以只要开源库没有被关闭,本文介绍的提取方法就一直适用; 比那些上传到下载平台就万年不更新的数据优秀很多。
查询效果展示:从这里随便拿的一个坐标:直观的效果如上图,在百度地图里面随便点选一下(或App定位获得的坐标)得到一个坐标,然后到数据库里面利用空间查询SQL就能查询到坐标所在的城市。
步骤一、下载省市区边界数据 到开源库里面下载最新的 ok_geo.csv.7z 文件(13M大小,解压130M+),点此下载。下载好后解压得到 ok_geo.csv,此文件内包含了最新全国所有的省市区县坐标边界矢量数据。
注:这个文件只包含三级(省市区)数据不含第四级(乡镇街道),如需乡镇坐标边界数据,可以请点此下载 ok_geo4_*.csv 文件(90MB+压缩包 导出后300M+)。
步骤二、解析CSV文件导入数据库 下载好的文件 ok_geo.csv 是纯文本文件,可以自行编写脚本进行解析,然后导进数据库中,自行解析处理比较复杂,请参考开源库内文档;开源库内提供了一个格式转换工具,此工具支持将CSV数据导入数据库,因此我们直接在下载数据时顺带把工具下载好,点此下载。
此转换工具除了支持将 ok_geo.csv 导入数据库外,还支持导出:sql、shp、geojson,和坐标系转换;还可执行自定义 JavaScript 脚本,扩展出丰富功能;软件是Windows版,如果需要在MacOs中用,可以用虚拟机。
转换工具执行导入数据库操作:
点击 选择ok_geo.csv文件 按钮,选择解压出来的CSV文件; 数据库设置中选择要导入的数据库类型,这里选的是MySQL,再填写数据库连接,包括:端口、数据库名称、账号密码; 点击导入数据库按钮,等待一会,大约3分钟左右,所有数据就都导入到了数据库按今天日期新建的表里面。 注:csv文件内的边界数据默认是高德地图GCJ-02火星坐标系,如果需要其他坐标系,比如百度的BD-09或GPS的WGS-84,可以通过高级脚本中的坐标系转换插件进行转换,选择好对应的插件后,点击应用就可以了,在导入数据库时会自动进行坐标系转换。
注:这个工具限制每次操作只可导出一个城市和它的下一级数据,导出少量数据还是很轻松的,所以我们可以多操作几次,将需要的城市数据全部导入数据库;比如要深圳的所有区县数据:第一遍导入全国所有的省,第二遍在城市名前缀中填写广东省(结尾带一个空格)导入广东所有的市,第三遍在城市名前缀中填写广东省 深圳市(结尾带一个空格)导入深圳所有的区。如果在密钥输入框中填写了密钥,此工具就没有这些限制了,开源库里面会不定期发放密钥搞福利,点击一次操作即可导出全国所有的省市区三级数据。
表结构和空间字段(MySQL版,其他数据库类似):
CREATE TABLE Areacity_Geo_20220216 ( id int NOT NULL, --城市id pid int NOT NULL, --上级城市id deep int NOT NULL, --层级:0省、1市、2区 name varchar(250) NOT NULL, --城市名称:`深圳市` ext_path varchar(255) NOT NULL, --省市区三级完整名称:广东省 深圳市 罗湖区 geo geometry NOT NULL, --城市中心坐标,空间数据格式 --,ST_AsText转成WKT文本后:`POINT EMPTY`、`POINT (123.
for循环
虽然所有循环结构都可以用while或者do..….while表示,但Java提供了另一种语句——for循环,使一些循环结构变得更加简单。 for循环语句是支持迭代的一种通用结构,是最有效、最灵活的循环结构。 for循环执行的次数是在执行前就确定的。语法格式如下: for(初始化;布尔表达式;更新){ //代码语句 } public static void main(String[] args) { int a = 1;//初始化条件 while (a <=100){//条件判断 System.out.println(a);//循环体 a += 2;//迭代 } System.out.println(while循环结束); for (int i = 1; i <= 100 ; i++) { System.out.println(i); } System.out.println(for循环结束); } 练习1:计算0到100之间的奇数和偶数的和
public static void main(String[] args) { //计算0-100之间的计算和偶数的和 int a = 0;///奇数 int b = 0;//偶数 for (int i = 0; i <=100; i++) { if(i%2!