Python与Java Socket传输yfinance股票数据中断及数据限制问题求助
问题:Socket传输股票数据时仅传输部分内容后挂起
我正在开发一款程序,用于整理并压缩多只股票的yfinance数据,最终存入.txt文件。程序通过Socket实现Python服务器向Java客户端传输数据,但运行时仅能传输部分数据,随后突然停止导致程序挂起。想问是否存在数据限制阻碍完整数据传输?
Python服务器代码
import socket import yfinance as yf import pandas as pd import datetime as dt pd.options.display.max_rows = 2000000 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind(("127.0.0.1", 65432)) s.listen() conn, addr = s.accept() with conn: print(f"Connected by {addr}") while True: data = conn.recv(1024) if not data: print('nodata') break stringdata = data.decode('utf-8') print(stringdata) if stringdata == "end": break start1 = stringdata[0:10] start = dt.datetime(int(start1[0:4]), int(start1[5:7]), int(start1[8:10])) end1 = stringdata[10:20] end = dt.datetime(int(end1[0:4]), int(end1[5:7]), int(end1[8:10])) tticker = yf.Ticker(stringdata[20:]) print(tticker.history(start=start, end=end, interval="5m")) stringdata2 = str(data2) print(stringdata2) conn.sendall(bytes(stringdata2, 'utf-8')) s.close()
Java客户端代码
import java.net.*; import java.text.NumberFormat; import java.text.ParseException; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.io.*; import java.util.Scanner; public class main{ public static ArrayList<String> Tickers = new ArrayList<String>(); public static File stockTracker = new File("StockTracking.txt"); public static void main(String[] args) throws IOException, ParseException, InterruptedException{ int x = 65; char y; String z; String x1; while(x <= 90) { y = (char)x; z = String.valueOf(y); x1 = "https://eoddata.com/stocklist/NYSE/" + z + ".htm"; URL tickers = new URL(x1); URLConnection tCon = tickers.openConnection(); InputStreamReader tStream = new InputStreamReader(tCon.getInputStream()); BufferedReader tBuff = new BufferedReader(tStream); String oline = tBuff.readLine(); while(oline != null) { if(oline.contains("NYSE,")){ String gx = oline.substring(oline.indexOf("/NYSE/") + 6, oline.indexOf(".htm")); if(!(gx.equals("BRK.A")) && !(gx.equals("EVN"))) { try { if(!(Integer.parseInt(oline.substring(oline.indexOf("<td align=right>") + 16, oline.indexOf("<td align=right>") + 17)) < 5 && oline.substring(oline.indexOf("<td align=right>") + 17, oline.indexOf("<td align=right>") + 18).equals(".")) && NumberFormat.getNumberInstance(java.util.Locale.US) .parse(oline.substring(oline.indexOf("<td align=right>") + 94, oline.indexOf("</td><td align=\"right\">"))).intValue() > 1000000) { Tickers.add(gx); System.out.println(gx); } }catch(ParseException e) { Tickers.add(gx); } } } oline = tBuff.readLine(); } y = (char)x; z = String.valueOf(y); x1 = "https://eoddata.com/stocklist/NASDAQ/" + z + ".htm"; URL ntickers = new URL(x1); URLConnection nCon = ntickers.openConnection(); InputStreamReader nStream = new InputStreamReader(nCon.getInputStream()); BufferedReader nBuff = new BufferedReader(nStream); String nline = nBuff.readLine(); while(nline != null) { if(nline.contains("NASDAQ,")){ String gx = nline.substring(nline.indexOf("/NASDAQ/") + 8, nline.indexOf(".htm")); try { if(!(Integer.parseInt(nline.substring(nline.indexOf("<td align=right>") + 16, nline.indexOf("<td align=right>") + 17)) < 5 && nline.substring(nline.indexOf("<td align=right>") + 17, nline.indexOf("<td align=right>") + 18).equals(".")) && NumberFormat.getNumberInstance(java.util.Locale.US) .parse(nline.substring(nline.indexOf("<td align=right>") + 94, nline.indexOf("</td><td align=\"right\">"))).intValue() > 1000000) { Tickers.add(gx); System.out.println(gx); } }catch(ParseException e) { Tickers.add(gx); } } nline = nBuff.readLine(); } x++; } for(String tick:Tickers) { System.out.println(tick); } Scanner console = new Scanner(System.in); Socket transmission = new Socket("localhost", 65432); System.out.println("Socket Created"); Reader reader = new InputStreamReader(transmission.getInputStream()); BufferedReader in = new BufferedReader(reader); Writer writer = new OutputStreamWriter(transmission.getOutputStream()); BufferedWriter out = new BufferedWriter(writer); FileWriter dWriter = new FileWriter("StockTracking.txt"); initData(in, out); out.write("end"); transmission.close(); System.out.println("Socket Closed"); } public static boolean initData(BufferedReader in, BufferedWriter out) throws IOException, InterruptedException { LocalDate edate = LocalDate.now().minusDays(1); LocalDate sdate = LocalDate.now().minusDays(40); String ssdate = sdate.format(DateTimeFormatter.ISO_LOCAL_DATE); String sedate = edate.format(DateTimeFormatter.ISO_LOCAL_DATE); PrintWriter pw = new PrintWriter(new FileWriter(stockTracker)); for(String ticker:Tickers) { System.out.println(ticker); out.write(ssdate + sedate + ticker); out.flush(); Thread.sleep(10); pw.println(ticker); String x; while(true) { x = in.readLine(); System.out.println(x); if(x.length() > 25 && x.substring(0, 1).equals("2")) { pw.println(x.substring(5, 7) + x.substring(8, 10) + x.substring(11, 13) + x.substring(14, 16) + x.substring(27, x.indexOf(".") + 2)); if(x.substring(5, 7).equals("07")) { if(x.substring(8, 10).equals("21")) { if(x.substring(11, 13).equals("15")) { if(x.substring(14, 16).equals("55")) { break; } } } } } } pw.flush(); } pw.close(); return false; } }
问题根源与解决方案
1. 核心语法错误(Python端)
print(tticker.history(...))缺少闭合括号,会直接导致程序崩溃中断。stringdata2 = str(data2)中的data2未定义,正确写法应为先获取历史数据再转换:data2 = tticker.history(start=start, end=end, interval="5m") stringdata2 = str(data2)
2. Socket流式传输的边界问题
Socket是无消息边界的流式协议,直接传输字符串会导致两端无法判断数据是否传输完成,进而引发挂起:
- Python端改进:在数据末尾添加明确的结束标记,告知客户端传输完成:
data2 = tticker.history(start=start, end=end, interval="5m") stringdata2 = str(data2) + "\nDATA_END\n" conn.sendall(stringdata2.encode('utf-8')) - Java端改进:替换原有的日期判断逻辑,改为读取直到遇到结束标记:
StringBuilder sb = new StringBuilder(); String line; while ((line = in.readLine()) != null) { if (line.equals("DATA_END")) { break; } sb.append(line).append("\n"); } String fullStockData = sb.toString(); // 处理数据写入文件
3. 数据接收截断问题
Python端conn.recv(1024)每次仅接收1024字节,若客户端发送的请求(日期+股票代码)超过该长度,会导致数据截断,解析时出错。需循环接收完整请求:
def recv_full_message(conn): buffer = b'' while True: chunk = conn.recv(1024) if not chunk: return None buffer += chunk if b'\n' in chunk: # 客户端发送请求时需添加换行标记 break return buffer.decode('utf-8').strip()
替换原代码中的data = conn.recv(1024)为stringdata = recv_full_message(conn),同时Java端发送请求时添加换行:
out.write(ssdate + sedate + ticker + "\n"); out.flush();
4. 资源释放问题
Python端使用with语句已自动处理Socket关闭,无需额外调用s.close();Java端需确保initData执行完毕后,关闭输入输出流,避免资源泄漏。
内容的提问来源于stack exchange,提问作者IneptDwarf33872
相关产品推荐
相关产品推荐

