Automate trade module in Tdxw
Code
# coding: utf-8
"""
Created on Thu Dec 07 10:57:45 2017
@author: duanqs
"""
#import pywinauto
from pywinauto import application, findwindows, findbestmatch
from pywinauto import clipboard
from pywinauto.application import Application
import SendKeys
#import win32gui
#import win32api
#import win32con
import os, sys, time
import pandas as pd
class Tdxw:
u'''
简介:
使用pywinauto对应用程序进行自动化操作的步骤以及方法:
1. 初始化一个application实例app:
app = application.Application()
2. 用该app实例启动目标应用程序
或者将该app实例连接到正在运行的目标程序:
app.start() or
app.connect(handle=xl_handle)
3. 开始操作程序的主窗口(mainDlg):
mainDlg = app.Notepad or
mainDlg = app['Notepad']
4. 进一步操作窗口里的控件, 比如TreeView控件:
tv = mainDlg.TreeView
tv.get_item().click_input()
FAQ:
1. 如何查看GUI里的窗口或者控件信息?
A: 用au3info.exe程序 或者 调用:
.print_control_identifier()方法
2. 查找窗口的方法有哪些?
A: findwindows.find_window()
findwindows.find_windows()
#==============================================================================
# print u'现在需要把app对象连接到GUI程序上, 以实现两个进程(python脚本/GUI程序)间通信'
# print u'通常分两步走:'
# print u'1. 找到GUI程序的窗口: 通常有两种方法来找到目标窗口的句柄'
# print u' 1. 用目标窗口的类名, 传值给class_name参数, 比如:'
# print u' pywinauto.findwindows.find_windows(class_name=\'Chrome_WidgetWin_1\')[0]'
# print u' 2. 用目标窗口的标题, 传值给title_re参数, 比如:'
# print u' pywinauto.findwindows.find_windows(title_re=u\'无标题\')[0]'
# print u'2. 用app.connect方法建立连接'
# print u'但是, 如果GUI程序是单个进程的话, 一步就可建立连接了. '
# print u'利用已经打开的GUI程序的路径或者句柄或者进程号三者之一, 比如:'
# print u'- app.connect(path=\'notepad\') # 传值给path参数'
# print u'- app.connect(handle=1442350) # 传值给handle参数'
# print u'- app.connect(process=4224) # '
#==============================================================================
功能:
automation class for 海通证券版通达信下单程序
'''
program_tdx = u'D:\\new_haitong\\TdxW.exe'
program_notepad = 'Notepad'
program = program_tdx
loginWinTitle = u'.*海通证券彩虹投资.*'
mm = 'xxxxxxxxx'
SLEEP_TIME = 1
DICT1 = {'mmjp':'AfxWnd42', #密码键盘
'dl':'AfxWnd422', #登录
'tj':'AfxWnd424', #脱机
'qx':'AfxWnd425', #取消
'txsz':'AfxWnd426', #通讯设置
'syzn':'AfxWnd427', #使用指南
'xtjc':'AfxWnd428', #系统检测
'wskh':'AfxWnd429', #网上开户
'hqjjy':'AfxWnd4210', #行情加交易
'dlhq':'AfxWnd4211', #独立行情
'dljy':'AfxWnd4212', #独立交易
}
XD_DICT = {u'查询':8,
u'资金股份':0,
u'当日委托':1,
u'当日成交':2,
u'历史委托':3,
u'历史成交':4,
u'成交汇总':5,
u'资金流水':6,
u'交割单':7,
}
class_tdx_xd = 'Afx:400000:8:10011:0:0'
class_tdxw = 'TdxW_MainFrame_Class'
class_explore = 'ExploreWClass'
# TreeView控件 操作子条目时的路径:
# 不知为何用中文文本方式的路径时, codec出错!!!
cx_zjgf = [8,0] #查询 资金股份
cx_drwt = [8,1] #查询 当日委托
cx_drcj = [8,2] #查询 当日成交
cx_lswt = [8,3] #查询 历史委托
cx_lscj = [8,4] #查询 历史成交
cx_cjhz = [8,5] #查询 成交汇总
cx_zjls = [8,6] #查询 资金流水
cx_jgd = [8,7] #查询 交割单
fname=''
def __init__(self):
pass
def startup(self):
print u'...实例化pywinauto App对象, 用缺省的构造函数'
app = Application()
# app = Application(backend='uia')
print u'...启动本机的GUI程序\'%s\', 通过app对象来启动, 以便后续进行自动化操作' %(self.program)
app.start(self.program) # , timeout=5)
# 等待登录窗口出现:
# 处理异常情况: 有可能出现第二次登录, 这时候应该点击"取消",然后退出脚本
mainDlg=app.window(title='',class_name='#32770')
if mainDlg.exists():
print mainDlg.Static2.window_text()
mainDlg[u'取消'].click_input()
# exit
sys.exit(0)
#time.sleep(5) # 1 sec 这种傻傻地等待的方法最安全了, 可以获取到pid
#app.WaitCPUUsageLower(threshold=25, timeout=10)
mainDlg=app.window(title_re=self.loginWinTitle, class_name='#32770')
while not mainDlg.Exists():
#while not app.windows_() or not app.TdxW_MainFrame_Class.Exists():
time.sleep(.5)
print u'...GUI程序已经启动, and its pid= %s, pid将用来建立进程间通信' %(app.process)
# 把此时的重要变量/数据保存给类实例的属性, 以便后续的方法里使用
# 注意属性名字 不要与方法同名
# 将app对象, app.window()对象:主窗口
self.app = app
self.mainDlg = app.window() # 获取 目标应用程序的主窗口(): 登录界面
# mainDlg = app.window(handle=w_handle)
# self.mainDlg.Close() # 关闭主窗口
#==============================================================================
def login_mode(self, mode='T'):
u'''
login with specific mode
param mode:
str, one of ('T', 'HQ', 'HQT')
分别表示: 独立交易 独立行情 交易+行情 模式
example:
tdx.login_mode('HQ')
'''
if mode == 'T':
self.loginTradeOnly()
elif mode == 'HQ':
self.loginHQOnly()
elif mode == 'HQT':
self.loginHQ_Trade()
def login(self):
u''' login HQ + trade
背景知识:
海通证券连接柜台中间件失败:
- 出现这个问题,很可能是证券公司系统测试,或者系统维护,
- 周六周日证券公司会搞系统测试,等周一就会好了。
- 再有就是看看您的网络连接,如果连接没问题就是在系统测试。
- 没事的周一就好了。
'''
self.mainDlg.Edit2.ClickInput() # Edit2 交易密码编辑框
SendKeys.SendKeys(self.mm)
SendKeys.SendKeys('{ENTER}')
#self.mainDlg.Edit4.ClickInput() # Edit4 通选密码编辑框
SendKeys.SendKeys(self.mm)
SendKeys.SendKeys('{ENTER}')
time.sleep(3)
def loginHQ_Trade(self):
u'''
行情+交易 登录
'''
# self.mainDlg.Edit.SetFocus(); # Edit : zjzh Edit Box
# SendKeys.SendKeys('1300148453{ENTER}')
#tdx.mainDlg[DICT1['hqjjy']].print_control_identifiers()
#tdx.mainDlg[DICT1['hqjjy']].DrawOutline() # 用来识别控件是否正确, 画个外框
self.mainDlg[self.DICT1['hqjjy']].Click()
time.sleep(self.SLEEP_TIME)
self.input_mm()
self.input_txmm() #通讯密码 , 然后回车就登录了
def loginHQOnly(self):
self.mainDlg[self.DICT1['dlhq']].Click()
time.sleep(self.SLEEP_TIME)
def loginTradeOnly(self):
self.mainDlg[self.DICT1['dljy']].Click()
self.input_mm()
self.input_txmm() #通讯密码 , 然后回车就登录了
def input_mm(self):
#self.mainDlg.SaveEdit1.print_control_identifiers() #交易密码 编辑框
self.mainDlg.Edit2.SetFocus()
SendKeys.SendKeys(self.mm)
SendKeys.SendKeys( '{ENTER}',pause=0.5, with_newlines=True) # 0.05 sec by default
time.sleep(self.SLEEP_TIME)
#==============================================================================
# # 另一种输入密码的方法: TypeKeys()
# ttt=2
# self.mainDlg.SaveEdit2.TypeKeys('4');time.sleep(ttt)
# self.mainDlg.SaveEdit2.TypeKeys('1');time.sleep(ttt)
# self.mainDlg.SaveEdit2.TypeKeys('6');time.sleep(ttt)
# self.mainDlg.SaveEdit2.TypeKeys('5');time.sleep(ttt)
# self.mainDlg.SaveEdit2.TypeKeys('8');time.sleep(ttt)
# self.mainDlg.SaveEdit2.TypeKeys('9{ENTER}')
#==============================================================================
print u'\n==> 交易密码已经输入完毕! entered!'
def input_txmm(self):
#self.mainDlg.SaveEdit3.print_control_identifiers() #通信密码 编辑框
self.mainDlg.Edit4.SetFocus()
SendKeys.SendKeys(self.mm)
SendKeys.SendKeys('{ENTER}', pause=0.5, with_newlines=True)
time.sleep(self.SLEEP_TIME)
print u'\n==> 通讯密码已经输入完毕!'
# 通讯密码输入之后,应该预留片刻时间,
# 等待 连接服务器/身份认证/下载权息信息等等事项
# 一直到出现交易界面窗口
#time.sleep(6)
while not self.app.TdxW_MainFrame_Class.exists():
time.sleep(0.5)
self.handle_login_failure()
def close_tsxx(self):
u'''
登录之后, 关闭'提示信息'窗口
备注:
1. 首次登录之后, 经常会遇到服务器发来的提示消息, 有时还不只1个消息窗口.
这些提示消息窗口的类名均为 #32770, 比如窗口名为"发现了新版本",
或者"发行新股提示"等待. 所以需要逐个关闭之.
>>> l_dlg= tdx.app.windows(class_name='#32770')
>>> print "|".join([d.texts()[0] for d in l_dlg])
>>> print "|".join([d.window_text() for d in l_dlg])
即时播报|发现了新版本|新股提示||滚动资讯|刷新行情
由此可见: tdx软件还有4个内置的消息窗口(Dialog控件)是不应该关闭的
2. texts() 与 window_text()方法的区别:
前者返回文本列表, 后者返回文本
3. app.windows() app.window()的区别:
前者返回封装了的对话框列表, 后者窗口规格对象
Dlgs =tdx.app.windows()
winSpec =tdx.app.window()
appWins == appWin # False
xxDlgs =tdx.app.windows(class_name='#32770')
xxWinSpec =tdx.app.window(class_name='#32770')
'''
# close 提示信息窗口
# 查找独立(非内嵌的)的消息窗口
handles = findwindows.find_windows(class_name='#32770')#[0]
if len(handles) > 0 :
for h in handles:
msgWin= self.app.window(handle=h)
print u'...关闭该窗口: "%s" '%(msgWin.window_text())
msgWin.Close()
print( u'\n==> 所有提示信息窗口 已经关闭!')
def close_client(self):
u''' close tdx交易客户端
'''
self.app.window(class_name=self.class_tdxw).Close()
def real_login_trade(self,closeTSXX=True):
u'''
'''
self.startup()
# tdx.login() # 登录到: 行情 + 交易 模式
# tdx.loginHQ_Trade()
# tdx.loginHQOnly()
# tdx.loginTradeOnly()
self.login_mode('T') # 'HQT' 'T' 'HQ'
time.sleep(self.SLEEP_TIME)
if closeTSXX:
self.close_tsxx()
# save 交易客户端的主界面
# 用au3info工具: 查看窗口信息: 窗口类名为 TdxW_MainFrame_Class
# mainFrame = tdx.app.window(class_name=tdx.class_tdx_xd)
self.mainDlg = self.app.window(class_name='TdxW_MainFrame_Class')
def connect_to(self, l_handle):
u'''
'''
app=Application().connect(handle=l_handle[0])
self.app=app
self.mainDlg=app.window(class_name=self.class_tdxw)
def modify_date_range(self, ymd1=(2017,7,1), ymd2=(2017,7,31)):
u'''修改查询日期: 起始日期, 结束日期
# 设置查询的起始日期 终止日期 然后 查询 输出
# 注意日期必须设置正确
mainDlg=tdx.app.window()
# 可以借助下面的方法,查找出时间拾取控件的独一无二的/没有分歧的 控件名
# mainDlg.print_control_identifiers(depth=2)
mainDlg.DateTimePicker.get_time()
mainDlg.DateTimePicker2.get_time()
# 或者更加明确的日期拾取控件名:
mainDlg[u'起始日期:DateTimePicker'].get_time()
mainDlg[u'终止日期:DateTimePicker2'].get_time()
mainDlg.DateTimePicker.wrapper_object().set_time(2019,1,0,1, 0,0,0,0)
mainDlg.DateTimePicker2.wrapper_object().set_time(2019,1,0,25, 0,0,0,0)
tdx.app.window()[u'查询'].click_input()
tdx.app.window()[u'输出'].click_input()
# 假如日期设置不正确, 会得到运行时错误, 比如2月份没有第31号
mainDlg.DateTimePicker2.wrapper_object().set_time(2018,2,0,31, 0,0,0,0)
RuntimeError: Failed to set time in Date Time Picker
'''
# based on dt1,dt2, create fileName 变量, 然后保存到实例对象里
self.yy1, self.mm1, self.dd1 = yy1,mm1,dd1 = ymd1 #(2017, 8, 1)
self.yy2, self.mm2, self.dd2 =yy2,mm2,dd2 = ymd2 #(2017, 8, 31)
#fname = u'd:\\DB\\tdxw\\'
#self.fname = u'%s%02d%02d-%s%02d%02d'%(yy1,mm1,dd1, yy2,mm2,dd2)
self.fname = u'%s%02d'%(yy1,mm1)
mainDlg = self.mainDlg = self.app.window(class_name=self.class_tdxw)
#mainDlg[u'起始日期:DateTimePicker'].get_time()
#mainDlg[u'终止日期:DateTimePicker2'].get_time()
dtp1=mainDlg[u'起始日期:DateTimePicker'] #.get_time()
dtp2=mainDlg[u'终止日期:DateTimePicker2'] #.get_time()
#dtp1_ = mainDlg.DatetimePick.wrapper_object()
#dtp2_ = mainDlg.DatetimePick2.wrapper_object()
dtp1.set_time(yy1,mm1,0,dd1, 0,0,0,0)#Year,M,DayOfWeek,D, H,M,S,ms
dtp2.set_time(yy2,mm2,0,dd2, 0,0,0,0)
mainDlg[u'查询'].ClickInput() #点击确定: 执行新的查询
#mainDlg[u'输出'].ClickInput() #点击确定: 执行新的查询
time.sleep(3) # 需要足够长才行, 否则结果没有出来
def get_query_result(self, content=87, yyyymm=201707,closeAppFlag=False):
u'''
86: 资金流水
87: 交割单
Example:
>>> tdx=Tdxw()
>>> tdx.get_query_result(content=86, yyyymm=201707 )
'''
l_handle=findwindows.find_windows(class_name=self.class_tdxw)
if len(l_handle)==1:
# 只需要connect to 应用程序就可以了
self.connect_to(l_handle)
pass
else:
self.real_login_trade()
main = self.mainDlg
cdic={
80:'zjgf.txt',
81:'drwt.txt',
82:'drcj.txt',
84:'lscj.txt',
86:'zjls.txt',
87:'jgd.txt',
}
idic={
80:self.cx_zjgf,
81:self.cx_drwt,
82:self.cx_drcj,
84:self.cx_lscj,
86:self.cx_zjls,
87:self.cx_jgd,
}
item_c = idic[content]
#
tv = main.TreeView
# 文本格式的路径, 不干活. 可见pywinauto对listview可见的支持不够完善!!!
#tv.get_item(u'\\市价委托\\买入').ClickInput()
#tv.get_item(u'\\\\\t查询\\\\交割单').ClickInput() #执行查询
#tv.get_item([u'\t查询', u'交割单']).ClickInput() #执行查询
# tv.get_item(self.cx_zjgf).ClickInput() #执行查询
# time.sleep(2)
#
# tv.get_item(self.cx_zjls).ClickInput() #执行查询
# time.sleep(2)
#
tv.get_item(item_c).ClickInput() #执行查询
time.sleep(2)
# 处理异常情况: "()通信失败, DrtpSend: 目的网关无法到达 "
#w=tdx.app.window(handle=findwindows.find_windows(class_name='#32770')[0])
w=self.app.window(title=u'提示',class_name='#32770')
if w.exists():
print u'... 有异常情况 ...'
print u'... %s ...'%w.window_text()
#Static2 很奇怪: 这样就是取不到 静态标签的文本
#print w.Static3.window_text()
# 只能这样才可以取得 该标签的文本
print w.children()[4].window_text()
w[u'确认'].click_input()
self.close_client()
sys.exit(0)
else:
lv = main.ListView
# #Allow the calling code to get the HwndWrapper object
# lv_hwnd_wr = lv.wrapper_object()
# 查看交割单列表视图的列名
# Why pywinauto fail to get ListView item from a 32-bit app? - Stack Overflow
# https://*.com/questions/46337375/why-pywinauto-fail-to-get-listview-item-from-a-32-bit-app?r=SearchResults
print '|'.join([dic['text'] for dic in lv.columns()])
#lv.click(button='right') # 会触发一个 弹出菜单: PopupMenu
##tdx.app.window(class_name='#32768') # 弹单的类名
#self.app.PopupMenu.MenuItem(u'输出').click_input()
#time.sleep(2) # 2sec
#self.app[u'输出'][u'输出到Excel表格'].click()
# 选取时间段, 然后查询
yyyymm=str(yyyymm)
y,m=int(yyyymm[:4]), int(yyyymm[-2:])
ymd1,ymd2 = (y,m,1),self.get_end_of_month(yyyymm)
self.modify_date_range(ymd1,ymd2)
outFile = '_'.join([self.fname, cdic[content]])
#也可以直接点击mainDlg里的输出按钮
main[u'输出Button'].click_input() #会弹出一个"输出"窗口
print self.app[u'输出'].Edit.get_line(0)
self.app[u'输出'].Edit.set_edit_text(outFile)
print self.app[u'输出'].Edit.get_line(0)
# 如何得到 输出文件名 编辑框 控件的id?
# 用 它的mainDlg的PrintCtrlId()方法来查看:
# self.app[u'输出'].print_control_identifiers()
self.app[u'输出'][u'确定Button'].click_input() # 保存文件,然后调用Excel读取之
time.sleep(2)
close_app(className='Notepad') #close excel
if closeAppFlag:
self.close_client() #close tdx app
pass
def print_ctrl_window_text(self, mainDlg):
u'''
打印主窗口里的控件的明面文本
'''
ctrl_window_text = [ctrl.window_text() for ctrl in mainDlg.children()]
for i, txt in enumerate(ctrl_window_text):
print i, txt
def print_ctrl_fClassName(self, mainDlg):
u'''
打印主窗口里的控件昵称(控件小名/控件亲切称呼)和控件文本
备注:
1. 枚举子控件的方法: children()
2. 获取控件昵称的方法: .friendly_class_name()
3. 获取控件文本的方法: .window_text()
示例: 比如当出现'发现了新版本'提示信息窗口时,
想知道这个主窗口里面的每一个控件的昵称和控件明面文本.
>>> tdx=Tdxw()
>>> tdx.real_login_trade(closeTXSS=False)
>>> mainDlg=tdx.app.window(title=u'发现了新版本')
>>> tdx.print_ctrl_fClassName(mainDlg)
Num 控件昵称 控件明面文本
----------------------------------------
0 Button 升级到新版本
1 Button 关闭
2 Static [海通证券彩虹投资(通达信)]新版本V2.13
3 CheckBox 一星期内不要提醒我
4 RICHEDIT
尊敬的投资者,您好!
海通证券彩虹投资(通达信)网上交易客户端已发布2.13最新版本,新增支持股转指数、优化资金股份高速刷新等,请您尽快升级。
同时,我司将于近期停止使用2.03及其以下版本,由此给您带来的不便,敬请谅解!
详情请咨询海通全国统一客服热线:95553、4008888001(联通用户)或海通e海通财在线客服。
海通证券股份有限公司
2019-01-15
'''
ctrl_fcns = [ctrl.friendly_class_name() for ctrl in mainDlg.children()]
ctrl_window_text = [ctrl.window_text() for ctrl in mainDlg.children()]
print '%3s %-16s %-20s'%('Num', u'控件昵称', u'控件明面文本')
print '--'*20
for i, c in enumerate(ctrl_fcns):
print '%3d %-20s %-20s'%(i, c , ctrl_window_text[i] )
def get_end_of_month(self, yyyymm):
u'''
获取'某年某月'的最后一天的日期
Example:
>>> get_end_of_month(1, 201902)
>>> get_end_of_month(1, 201802)
>>> get_end_of_month(1, 201702)
>>> get_end_of_month(1, 201602)
>>> get_end_of_month(1, 201502)
(2015, 2, 28)
'''
# yyyymm=201902
yyyymm=str(yyyymm)
yyyy,mm=yyyymm[:4], yyyymm[-2:]
s=str(yyyy)+str(mm)+str('05')
fmt='%Y%m%d'
dt=pd.datetime.strptime(s,fmt)
e_o_m=dt + pd.tseries.offsets.DateOffset(months=1, days= -dt.day)
y=e_o_m.year
m=e_o_m.month
d=e_o_m.day
return y,m,d
def handle_login_failure(self):
u'''
'''
h=findwindows.find_windows(class_name='#32770',process=self.app.process)
if len(h)>=2:
print u'... 登录时有异常情况 ...'
dlg=self.app.window(handle=h[0])
if dlg.exists():
print dlg.window_text()
self.print_ctrl_fClassName(dlg)
print dlg.Static2.window_text()
dlg[u'确定'].click_input()
h=findwindows.find_windows(class_name='#32770',process=self.app.process)
dlg=self.app.window(handle=h[0])
if dlg.exists():
print dlg.window_text()
dlg.close()
sys.exit(0)
def get_jgd_fwf_width(self):# ifile=r'd:\DB\tdxw\201707_jgd.txt'):
u'''
获取交割单txt文件,fwf固定宽度的格式化的表格文件的每列宽度
>>> get_jgd_fwf_width(1,1)
'''
#of=r'd:\DB\tdxw\201707_jgd.txt'
of=self.ifile
with open(of) as fh: # mode的默认为: 'rb'
# 抛弃前两行垃圾
line=fh.readline()
line=fh.readline()
ss=line=fh.readline()
print line
type(line) #str 字节串
u=line.decode('gbk') #unicode 字符串
print len(line), len(u) #不相等的, 如果有中文的话
assert len(line) != len(u)
for i,line in enumerate(fh):
print i, len(line), len(line.decode('gbk'))
# 退出with语句块, (fh会被自动关闭), with语句的好处
s='\xb9\xc9\xb6\xab\xb4\xfa\xc2\xeb \xb3\xc9\xbd\xbb\xc8\xd5\xc6\xda \xd6\xa4\xc8\xaf\xb4\xfa\xc2\xeb \xd6\xa4\xc8\xaf\xc3\xfb\xb3\xc6 \xba\xcf\xcd\xac\xb1\xe0\xba\xc5 \xb2\xd9\xd7\xf7 \xb9\xc9\xc6\xb1\xd3\xe0\xb6\xee \xb3\xc9\xbd\xbb\xca\xfd\xc1\xbf \xb3\xc9\xbd\xbb\xbc\xdb\xb8\xf1 \xb3\xc9\xbd\xbb\xbd\xf0\xb6\xee \xd3\xb6\xbd\xf0 \xd3\xa1\xbb\xa8\xcb\xb0 \xb9\xfd\xbb\xa7\xb7\xd1 \xbd\xe1\xcb\xe3\xb7\xd1 \xc6\xe4\xcb\xfb\xb7\xd1 \xb1\xe4\xb6\xaf\xbd\xf0\xb6\xee \xd7\xca\xbd\xf0\xd3\xe0\xb6\xee \xb1\xd2\xd6\xd6 \n'
assert s==ss
print s.decode('gbk')
#"股东代码 成交日期 证券代码 证券名称 合同编号 操作 股票余额 成交数量 成交价格 成交金额 佣金 印花税 过户费 结算费 其他费 变动金额 资金余额 币种 "
# 123456789012345678
# 1234567890123456
# 1234567890123456
# 1234567890123456
# 1234567890123456
# 123456789012
#"股东代码 成交日期 证券代码 证券名称 合同编号 操作 股票余额 成交数量 成交价格 成交金额 佣金 印花税 过户费 结算费 其他费 变动金额 资金余额 币种 "
# 1234567890123456
# 1234567890123456
# 1234567890123456
# 12345678901234567
# 1234567890123
# 12345678901234
me=[c for c in s.strip().split(' ') if c !='']
print me
colspecs=[]
for i,c in enumerate(me):
if i==0:
pos1=s.find(c)
else:
pos2=s.find(c)
col= (pos1,pos2)
print col
colspecs.append(col)
pos1=pos2
colspecs.append((pos2,len(s)-1))
# print colspecs
# print len(colspecs)
width= [t[1]-t[0] for t in colspecs]
print width
#return colspecs, width
self.colspecs,self.width=colspecs,width
def read_jgd_fwf_txt(self, ifile=r'd:\DB\tdxw\201707_jgd.txt'):
u'''
>>> tdx=Tdxw()
>>> tdx.read_jgd_fwf_txt()
>>> df=tdx.df_jgd
#https://*.com/questions/19472566/python-read-fwf-error-dtype-is-not-supported-with-python-fwf-parser
'''
of=self.ifile=ifile
self.colspecs=[] # 必须先初始化该 实例变量
#colspecs, width = self.get_jgd_fwf_width()
self.get_jgd_fwf_width() # will fill colspecs
to_gbk=lambda x: x.decode('gbk')
conver={0:str, 2:str,3:to_gbk, 5:to_gbk, }
df=pd.read_fwf(of, skiprows=[0,1],
colspecs=self.colspecs,
header=0,
converters=conver,
#encoding='gbk', #没有起作用
) # c
# 用传递width参数列宽的方式, 读取数据时, 还是有问题???
# dfw=pd.read_fwf(of, skiprows=[0,1],width=width, header=0, converters={0:str, 2:str},) # c
# assert df.values==dfw.values
# assert df.shape == dfw.shape
df.columns= [c.decode('gbk') for c in df.columns]
df=df.drop(labels=[u'结算费',u'其他费',u'币种'], axis=1)
#array2d = df.values
# 在读取时, 利用converter参数, 传值一个转换函数的字典, 可以避免之后的列数据转换
# df[u'证券名称'] = [v.decode('gbk') for v in df[u'证券名称']]
# df[u'操作'] = [v.decode('gbk') for v in df[u'操作']]
# dtype 再搞一搞就行了!!!
self.df_jgd=df
#%%
def close_app(className='XLMAIN'):
u'''
close excel app started within tdx app
Note:
'XLMAIN' for excel app
'Notepad' for 记事本app
'''
xl_handle=findwindows.find_window(class_name=className)
if xl_handle:
xlsApp=Application().connect(handle=xl_handle)
xlsApp.window().close()
#%%
#def query_jgd():
# tdx=Tdxw()
# tdx.get_query_result(content=86, yyyymm=201707 )
# tdx.get_query_result(content=87, yyyymm=201707)
# tdx.get_query_result(content=84, yyyymm=201707,)
# tdx.get_query_result(content=84, yyyymm=201707,closeAppFlag=True)
#%%
#query_jgd()