python字典读取不报错

本文介绍了在Python中从字典中高效且安全地获取数据的方法,包括使用jsonpath、glom、get()方法以及自定义类和defaultdict来处理嵌套字典和缺失键的情况。

一说起字典中获取数据,我去这多简单

小案例上来:

#方法一
from jsonpath import jsonpath
ss = {"a":1,"b":2}
result = jsonpath(ss,"$..a")[0]
print(result)
#方法二
​
from glom import glom
result = glom(ss,'a')
print(result)
#方法三
result = ss.get("a")
#方法四
result = ss['a']
​多简单,再来一个案例,我们遇到的实际情况,可不是这么简单:
ss = {
    "data":[
        {"name":"a1","age":18},
        {"name":"a2","age":15},
        {"name":"a3"},
    ]
}
#我们要获取name和对应age
for s in ss["data"]:
    #这么写
    name = s["name"]
    age = s["age"]
    #还是这么写
    name = jsonpath(s,"$..name")[0]
    age = jsonpath(s,"$..age")[0]
​
    # 这么写给
    name = glom(s,'name')

    age = glom(s,'age')
    
都会报错:
我们只能用 get()
 name = s.get("name","")
 age = s.get("age","")

每次这么写感觉会很麻烦,后来发现可以自定义类的方式,每次把字典先格式化一下,无对应值返回None

我们自定义一个类,继承dict,然后实现它的__missing__方法:
​
class OurDict(dict):
    def __missing__(self, key):
        return None
​
a = OurDict({'a': 1, 'b': 2})
print(a['x'])

 

在在后来,在 Python 的collections工具模块中,有一个defaultdict实现了类似的事情。我们看它的使用方法

from collections import defaultdict
​
a = defaultdict(str)
a['a'] = 1
a['b'] = 2
print(a)
print(a['x'])
print(a)

a = defaultdict(str)接收一个函数,让a变量成为一个defaultdict类型的对象,它可以像普通字典一样被赋值和读取。

但是当你读取一个不存在的 key 时,它会自动生成一个默认值,并把默认值和这个 key 插入到字典中。这个默认值取决于你在defaultdict传入的参数。如果传入的是str那么默认值就是空字符串,如果是int那么默认值就是0.当然你也可以传入自定义的一个函数,从而控制这个默认值。

 

over

<think> 在Python多进程编程中,使用`input()`函数可能会引发异常,因为子进程的标准输入(stdin)通常没有正确关联到主进程的控制台输入。这会导致`EOFError`或`OSError`。以下是解决方案: ### 问题分析 当在子进程中调用`input()`时,由于子进程的标准输入流没有正确重定向,它会立即遇到文件结束(EOF),从而引发`EOFError: EOF when reading a line`。 ### 解决方案 有以下几种方法解决多进程中的输入问题: #### 方法1:避免在子进程中使用`input()` 最佳实践是将所有用户交互放在主进程中,然后通过进程间通信(IPC)将数据传递给子进程。 ```python from multiprocessing import Process, Queue def worker(input_queue): """子进程从队列获取输入数据""" data = input_queue.get() print(f"子进程接收到: {data}") if __name__ == "__main__": # 主进程获取用户输入 user_input = input("主进程请输入: ") # 创建队列并传递数据 input_queue = Queue() p = Process(target=worker, args=(input_queue,)) p.start() # 将输入数据放入队列 input_queue.put(user_input) p.join() ``` #### 方法2:重定向子进程的标准输入(仅适用于类Unix系统) 在类Unix系统(Linux/macOS)中,可以使用`sys.stdin`重定向,但Windows支持。 ```python import sys from multiprocessing import Process def safe_input(): """尝试安全读取输入""" try: return input("子进程请输入: ") except EOFError: return "子进程输入失败" if __name__ == "__main__": # 仅在Unix-like系统有效 if sys.platform not in ['linux', 'darwin']: print("警告: 此方法仅适用于类Unix系统") p = Process(target=safe_input) p.start() p.join() ``` #### 方法3:使用`multiprocessing.Manager`创建共享输入 通过Manager创建一个共享的输入变量,但输入操作仍需在主进程执行。 ```python from multiprocessing import Manager, Process def worker(shared_data): print("子进程读取:", shared_data['input']) if __name__ == "__main__": with Manager() as manager: shared_dict = manager.dict() # 主进程获取输入 shared_dict['input'] = input("主进程输入: ") p = Process(target=worker, args=(shared_dict,)) p.start() p.join() ``` ### 错误处理示例 当子进程意外调用`input()`时,如何捕获异常: ```python from multiprocessing import Process def risky_task(): try: data = input("子进程尝试输入: ") except EOFError as e: print(f"子进程捕获异常: {e}") data = "默认值" print("子进程继续执行...") if __name__ == "__main__": p = Process(target=risky_task) p.start() p.join() ``` ### 跨平台输入解决方案 对于需要从子进程获取用户输入的复杂场景,建议: 1. 使用主进程作为唯一输入点 2. 通过IPC传递输入指令 3. 使用网络套接字或命名管道实现跨进程输入 ```python # 示例:使用Queue传递输入指令 from multiprocessing import Process, Queue import time def interactive_worker(cmd_queue): while True: if not cmd_queue.empty(): command = cmd_queue.get() if command == "exit": break print(f"执行命令: {command}") time.sleep(1) if __name__ == "__main__": cmd_queue = Queue() p = Process(target=interactive_worker, args=(cmd_queue,)) p.start() while True: user_cmd = input("输入命令 (输入'exit'退出): ") cmd_queue.put(user_cmd) if user_cmd == "exit": break p.join() ``` ### 关键结论 1. **设计原则**:在多进程架构中,应将所有用户交互保留在主进程 2. **错误处理**:子进程中使用`input()`必须捕获`EOFError` 3. **跨平台限制**:Windows系统对子进程的标准输入有严格限制 §§相关问题§§: 1. 如何在Python多线程中使用`input()`函数? 2. 多进程间如何进行实时双向通信? 3. 如何通过管道(Pipe)实现进程间输入重定向? 4. 在Windows系统下多进程输入有哪些特殊限制? </think> # Python 多进程中使用 `input()` 报错的解决方案 在 Python 多进程环境中使用 `input()` 函数会引发 `EOFError`,这是因为子进程的标准输入(stdin)没有正确连接到控制台。下面是详细分析和解决方案: ## 问题分析及解决方案 ### 问题重现代码 ```python from multiprocessing import Process def child_process(): try: # 在子进程中尝试获取用户输入 user_input = input("子进程请输入: ") print(f"您输入了: {user_input}") except EOFError as e: print(f"错误发生: {e}") print("原因: 子进程的标准输入(stdin)未连接到控制台") if __name__ == "__main__": p = Process(target=child_process) p.start() p.join() ``` ### 输出结果 ``` 错误发生: EOF when reading a line 原因: 子进程的标准输入(stdin)未连接到控制台 ``` ## 解决方案 ### 方案1: 主进程处理所有输入(推荐) 将所有用户输入集中在主进程中处理,然后通过IPC传递给子进程: ```python from multiprocessing import Process, Queue import time def worker(input_queue): """子进程工作函数""" print("子进程开始工作...") # 等待并获取来自主进程的输入 while input_queue.empty(): time.sleep(0.1) user_input = input_queue.get() print(f"子进程收到: {user_input}") # 处理输入... if __name__ == "__main__": # 创建通信队列 input_queue = Queue() # 启动子进程 p = Process(target=worker, args=(input_queue,)) p.start() # 主进程获取用户输入 user_input = input("主进程请输入: ") # 将输入发送给子进程 input_queue.put(user_input) p.join() print("程序结束") ``` ### 方案2: 使用 `multiprocessing.Manager` 共享输入 通过管理器创建共享字典存储输入数据: ```python from multiprocessing import Process, Manager import time def shared_input_worker(shared_data): """等待共享输入的子进程""" print("子进程等待输入...") # 轮询等待输入 while not shared_data['has_input']: time.sleep(0.1) print(f"子进程收到: {shared_data['user_input']}") if __name__ == "__main__": with Manager() as manager: # 创建共享字典 shared_dict = manager.dict() shared_dict['has_input'] = False shared_dict['user_input'] = "" p = Process(target=shared_input_worker, args=(shared_dict,)) p.start() # 主进程获取输入 user_input = input("主进程请输入: ") # 更新共享数据 shared_dict['user_input'] = user_input shared_dict['has_input'] = True p.join() print("程序结束") ``` ### 方案3: 使用 `threading` 处理输入(适用于简单场景) 在主进程中使用线程处理输入,然后传递给子进程: ```python from multiprocessing import Process, Queue import threading def input_thread(input_queue): """专用的输入线程""" while True: try: data = input("请输入 (输入 'exit' 退出): ") if data.lower() == 'exit': input_queue.put('exit') break input_queue.put(data) except EOFError: break def processor(input_queue): """处理输入的子进程""" while True: if not input_queue.empty(): data = input_queue.get() if data == 'exit': print("子进程终止") break print(f"处理中: {data}") if __name__ == "__main__": input_queue = Queue() # 启动输入处理线程 input_thread = threading.Thread(target=input_thread, args=(input_queue,)) input_thread.daemon = True input_thread.start() # 启动处理子进程 p = Process(target=processor, args=(input_queue,)) p.start() # 等待进程结束 input_thread.join() p.join() ``` ## 替代 `input()` 的跨进程输入方案 ### 使用网络套接字实现跨进程输入 ```python from multiprocessing import Process import socket def socket_server(): """接收输入的套接字服务器""" server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind(('localhost', 12345)) server.listen(1) print("输入服务器已启动,等待连接...") conn, addr = server.accept() print(f"连接来自: {addr}") with conn: while True: data = conn.recv(1024).decode() if not data or data == 'exit': break print(f"服务器收到: {data}") def socket_client(): """发送输入的客户端""" client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect(('localhost', 12345)) while True: try: msg = input("客户端请输入: ") client.send(msg.encode()) if msg == 'exit': break except EOFError: break client.close() if __name__ == "__main__": server_process = Process(target=socket_server) client_process = Process(target=socket_client) server_process.start() client_process.start() client_process.join() server_process.terminate() # 终止服务器进程 ``` ## 关键结论 1. **根本原因**:子进程的stdin未连接到控制台 2. **最佳实践**: - 所有用户输入在主进程处理 - 使用队列(Queue)或共享内存传递数据 - 避免在子进程中直接使用`input()` 3. **替代方案**: - 使用网络套接字进行进程间通信 - 使用文件或数据库作为中间存储 4. **错误处理**: ```python try: user_input = input("请输入: ") except EOFError: print("警告:在子进程中无法直接获取用户输入") # 回退到其他输入方案... ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值