base.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. import os
  2. import copy
  3. import configparser
  4. from module.base_mode.module_aes import Aes
  5. import exifread
  6. from natsort import ns, natsorted
  7. import shutil
  8. from hashlib import sha256, md5
  9. import requests
  10. from datetime import datetime
  11. # 获取digicam的路径
  12. def check_install_path(other):
  13. path_list = []
  14. path_list.append(other)
  15. path_list.append(r"D:\Program Files (x86)\digiCamControl\CameraControl.exe")
  16. path_list.append(r"C:\Program Files (x86)\digiCamControl\CameraControl.exe")
  17. path_list.append(r"D:\Program Files\digiCamControl\CameraControl.exe")
  18. path_list.append(r"C:\Program Files\digiCamControl\CameraControl.exe")
  19. for i in path_list:
  20. if os.path.exists(i):
  21. return i
  22. return ""
  23. # 输入文件夹,并检查是否是一个正常的图片文件夹。
  24. def check_goods_folder(folder_path):
  25. all_files = os.listdir(folder_path)
  26. for file in all_files:
  27. file_path = "{}/{}".format(folder_path, file)
  28. if not os.path.isdir(file_path):
  29. continue
  30. if "原始图" in os.listdir(file_path):
  31. return folder_path
  32. # 上述检查不通过,可能是选择目录错误
  33. if "原始图" in all_files:
  34. root_path, _ = os.path.split(folder_path)
  35. return root_path
  36. return None
  37. def download_file(url, file_path):
  38. try:
  39. root_path, file_name = os.path.split(file_path)
  40. check_path(root_path)
  41. response = requests.get(url)
  42. _content = response.content
  43. with open(file_path, 'wb') as f:
  44. f.write(_content)
  45. print("下载成功:{}".format(file_path))
  46. except:
  47. print("下载失败:{}".format(file_path))
  48. def calculate_sha256(file_path):
  49. """Calculate the sha256 hash of the given file."""
  50. sha256_hash = sha256()
  51. try:
  52. with open(file_path, "rb") as f:
  53. # Read and update hash string value in blocks of 4K
  54. for byte_block in iter(lambda: f.read(4096), b""):
  55. sha256_hash.update(byte_block)
  56. return sha256_hash.hexdigest()
  57. except FileNotFoundError:
  58. print(f"The file {file_path} does not exist.")
  59. return None
  60. except Exception as e:
  61. print(f"An error occurred: {e}")
  62. return None
  63. def get_modified_time(file_path):
  64. # 获取文件最后修改的时间戳
  65. timestamp = os.path.getmtime(file_path)
  66. # 将时间戳转换为datetime对象,并格式化为指定格式的字符串
  67. modified_time = datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d %H:%M:%S')
  68. return modified_time
  69. def download_file_to_io(url):
  70. try:
  71. # 发送GET请求
  72. response = requests.get(url)
  73. # 检查请求是否成功
  74. response.raise_for_status() # 如果响应状态码不是200,会抛出HTTPError异常
  75. # 返回响应内容,以文本形式(对于HTML、JSON等文本内容)
  76. return response.text
  77. # 或者返回原始的二进制内容(对于图片、文件等非文本内容)
  78. # return response.content
  79. except requests.RequestException as e:
  80. print(f"An error occurred: {e}")
  81. return None
  82. def get_md5(file_path):
  83. data_md5 = None
  84. if os.path.isfile(file_path):
  85. f = open(file_path, 'rb')
  86. md5_obj = md5()
  87. md5_obj.update(f.read())
  88. hash_code = md5_obj.hexdigest()
  89. f.close()
  90. data_md5 = str(hash_code).lower()
  91. return data_md5
  92. def list_dir(path):
  93. listdir = os.listdir(path)
  94. return natsorted(listdir, alg=ns.PATH)
  95. # 通用串口数据解析器
  96. def get_data_from_receive_data(receive_data, start, len_data, data_magnification=1):
  97. # data_magnification 数据放大倍数,或缩小倍数,默认为1
  98. try:
  99. if len_data == 1:
  100. data = receive_data[start]
  101. return data * data_magnification
  102. elif len_data == 2:
  103. data = receive_data[start] << 8 | receive_data[start + 1]
  104. return data * data_magnification
  105. elif len_data == 4:
  106. data = receive_data[start] << 24 | receive_data[start + 1] << 16 | receive_data[start + 2] << 8 | \
  107. receive_data[start + 3]
  108. return data * data_magnification
  109. return None
  110. except:
  111. return None
  112. def get_images(path):
  113. _Type = [".png", ".PNG", ".jpg", ".JPG", ".gif", ".GIF", ".jpge", ".JPGE", ".CR2"]
  114. image_list = [] # 过滤非图片数据
  115. for _file in list_dir(path):
  116. file_name, e = os.path.splitext(_file)
  117. file_path = "{}/{}".format(path, _file)
  118. if os.path.isdir(file_path):
  119. continue
  120. if e in _Type and "mask" not in file_name:
  121. image_list.append(
  122. {
  123. "file_path": file_path,
  124. "file_name": file_name,
  125. "file": _file,
  126. "root_path": path,
  127. "e": e,
  128. }
  129. )
  130. return image_list
  131. def get_image_mask(path):
  132. _Type = [".png", ".PNG", ".jpg", ".JPG", ".gif", ".GIF", ".jpge", ".JPGE", ".CR2"]
  133. image_list = [] # 过滤非图片数据
  134. for _file in list_dir(path):
  135. file_name, e = os.path.splitext(_file)
  136. file_path = "{}/{}".format(path, _file)
  137. if os.path.isdir(file_path):
  138. continue
  139. if e in _Type and file_name == "mask":
  140. image_list.append(
  141. {
  142. "file_path": file_path,
  143. "file_name": file_name,
  144. "file": _file,
  145. "root_path": path,
  146. "e": e,
  147. }
  148. )
  149. return image_list
  150. # 删除文件夹下的所有文件
  151. def remove_all_file(directory):
  152. try:
  153. shutil.rmtree(directory)
  154. os.makedirs(directory)
  155. except Exception as e:
  156. print(f'Failed to clear directory {directory}. Reason: {e}')
  157. # 删除文件
  158. def remove_files(file_path):
  159. try:
  160. if os.path.exists(file_path):
  161. os.remove(file_path)
  162. return True
  163. except BaseException as e:
  164. print("base 188", e)
  165. return False
  166. def get_folder(path):
  167. folder_list = []
  168. for _file in list_dir(path):
  169. file_path = "{}/{}".format(path, _file)
  170. if os.path.isdir(file_path):
  171. folder_list.append(
  172. {"folder_path": file_path,
  173. "folder_name": _file,
  174. "root_path": path,
  175. "label": "待处理", # 是否需要继续处理
  176. }
  177. )
  178. return folder_list
  179. # 获取所有货号颜色 文件夹
  180. def get_all_goods_art_no_folder(path):
  181. folder_list = []
  182. if not os.path.exists(path):
  183. return folder_list
  184. if os.path.isfile(path):
  185. return folder_list
  186. temp_folder_list = get_folder(path)
  187. for folder_data in temp_folder_list:
  188. _p = "{}/原始图".format(folder_data["folder_path"])
  189. if os.path.exists(_p):
  190. folder_list.append(folder_data)
  191. return folder_list
  192. def get_date_time_original(file_path):
  193. with open(file_path, "rb") as file_data:
  194. tags = exifread.process_file(file_data)
  195. if "EXIF DateTimeOriginal" in tags:
  196. return str(tags["EXIF DateTimeOriginal"])
  197. else:
  198. return False
  199. def get_data_from_hqt(goods_number_list, get_online_data_ins):
  200. _goods_number_list = copy.deepcopy(goods_number_list)
  201. _list = []
  202. # 单次请求数少于20个
  203. goods_number_dict = {}
  204. while _goods_number_list:
  205. goods_art_no = _goods_number_list.pop()
  206. if "NUM" in goods_art_no:
  207. goods_art_no = goods_art_no.replace("NUM", "")
  208. _list.append(goods_art_no)
  209. if len(_list) == 20 or len(_goods_number_list) == 0:
  210. online_goods_art_data = get_online_data_ins.get_goods_art_no_info(
  211. numbers_list=_list
  212. )
  213. if online_goods_art_data:
  214. for number in online_goods_art_data:
  215. goods_number_dict["NUM" + number] = online_goods_art_data[number]
  216. _list = []
  217. return goods_number_dict
  218. def get_data_from_hqt_with_goods_art_no(goods_art_no_list, get_online_data_ins):
  219. _goods_art_no_list = copy.deepcopy(goods_art_no_list)
  220. _list = []
  221. # 单次请求数少于20个
  222. goods_art_no_dict = {}
  223. while _goods_art_no_list:
  224. goods_art_no = _goods_art_no_list.pop()
  225. _list.append(goods_art_no)
  226. if len(_list) == 20 or len(_goods_art_no_list) == 0:
  227. online_goods_art_data = get_online_data_ins.get_goods_art_no_info(
  228. goods_art_list=_list
  229. )
  230. if online_goods_art_data:
  231. for _goods_art_no in online_goods_art_data:
  232. goods_art_no_dict[_goods_art_no] = online_goods_art_data[
  233. _goods_art_no
  234. ]
  235. _list = []
  236. return goods_art_no_dict
  237. def load_config_form_ini(config_path):
  238. config = configparser.ConfigParser()
  239. if os.path.exists(config_path):
  240. try:
  241. config.read(config_path, encoding="utf-8")
  242. except:
  243. config.read(config_path)
  244. return config
  245. def set_config_to_int(config_ins, config_path, data_dict, section="basicSetup"):
  246. for i in data_dict:
  247. config_ins.set(section=section, option=i, value=data_dict[i])
  248. try:
  249. config_ins.write(open(config_path, "w", encoding="utf-8"))
  250. except:
  251. config_ins.write(open(config_path, "w"))
  252. # try:
  253. # config_ins.read(config_path, encoding="utf-8")
  254. # except:
  255. # config_ins.read(config_path)
  256. return config_ins
  257. def get_config(config_ins, key, section="basicSetup"):
  258. config_dict1 = config_ins.items(section)
  259. __config_dict = {}
  260. for i, k in config_dict1:
  261. __config_dict[i] = k
  262. if key in __config_dict:
  263. return __config_dict[key]
  264. else:
  265. return None
  266. def get_config_by_items(config_dict):
  267. __config_dict = {}
  268. for i, k in config_dict:
  269. __config_dict[i] = k
  270. return __config_dict
  271. def get_dict_value(_dict, key, default=None):
  272. if key in _dict:
  273. return _dict[key]
  274. else:
  275. return default
  276. def set_key(authorization, SecretKey, SecretIv):
  277. # --------------------用户身份--------------
  278. if authorization:
  279. authorization = Aes().get_key(authorization, SecretKey, SecretIv)
  280. with open("key", "w") as f:
  281. f.write(authorization)
  282. return authorization
  283. def print_dic(_dict):
  284. for i, v in _dict.items():
  285. print("{}:{}".format(i, v))
  286. print("\n")
  287. def check_path(_path):
  288. if not os.path.exists(_path):
  289. # 创建多级目录
  290. os.makedirs(_path, exist_ok=True)
  291. # os.mkdir(_path)
  292. return True
  293. def move_folders(path_list, target_folder):
  294. if not os.path.exists(target_folder):
  295. os.makedirs(target_folder)
  296. for source_folder in path_list:
  297. shutil.move(source_folder, target_folder)
  298. # 给定一个图片路径,如果 是原始图下的则返回对应已扣图等信息。否则只返回基础信息
  299. def get_cutout_image_info(source_image_path):
  300. if not os.path.exists(source_image_path):
  301. return None
  302. if os.path.isdir(source_image_path):
  303. return None
  304. data = {}
  305. source_root_path, source_file = os.path.split(source_image_path)
  306. source_file_name, source_file_extension = os.path.splitext(source_file)
  307. print("---------------source_root_path--------------------")
  308. print(source_root_path)
  309. print(source_root_path[-3:])
  310. # if source_root_path[-3:] != "原始图":
  311. # return None
  312. data["source_image_path"] = source_image_path
  313. data["source_root_path"] = source_root_path
  314. data["source_file"] = source_file
  315. data["source_file_name"] = source_file_name
  316. data["source_file_extension"] = source_file_extension
  317. cutout_image_path = "{}/原始图_已抠图/{}.png".format(source_root_path[:-3], source_file_name)
  318. if not os.path.exists(cutout_image_path):
  319. data["cutout_image_path"] = None
  320. return data
  321. cutout_image_root_path, cutout_image_file = os.path.split(cutout_image_path)
  322. cutout_image_file_name, cutout_image_file_extension = os.path.splitext(cutout_image_file)
  323. data["cutout_image_path"] = cutout_image_path
  324. data["cutout_image_root_path"] = cutout_image_root_path
  325. data["cutout_image_file"] = cutout_image_file
  326. data["cutout_image_file_name"] = cutout_image_file_name
  327. data["cutout_image_file_extension"] = cutout_image_file_extension
  328. return data
  329. # 指定一个列表,指定一个需要移动的数据列表,移动到指定列表中的位置
  330. def move_elements_inplace(lst, indices, target_index, is_real_same_folder=False):
  331. """
  332. 在原地将列表中指定位置的两个元素移动到目标位置。
  333. :param lst: 要操作的列表
  334. :param indices: 一个包含两个整数的元组或列表,表示要移动的元素的索引
  335. :param target_index: 目标插入位置的索引
  336. """
  337. if not isinstance(indices, (list, tuple)) or len(indices) == 0:
  338. raise ValueError("Indices must be a non-empty list or tuple of integers.")
  339. # 添加到末尾
  340. if target_index == len(lst):
  341. if is_real_same_folder:
  342. # 倒序取出所有内容,并添加到末尾
  343. indices.sort(reverse=True)
  344. temp = []
  345. for i in indices:
  346. temp.append(lst.pop(i))
  347. while temp:
  348. lst.append(temp.pop(-1))
  349. # 重新写入索引
  350. for index, image_label in enumerate(lst):
  351. image_label.image_index = index
  352. return
  353. # 检查索引是否有效,并排序以确保按照正确的顺序处理
  354. valid_indices = sorted(set(indices)) # 去重并排序
  355. if not all(0 <= idx < len(lst) for idx in valid_indices):
  356. raise IndexError("One or more indices are out of range.")
  357. if not (0 <= target_index <= len(lst)):
  358. raise IndexError("Target index is out of range.")
  359. elements_to_move = [lst[idx] for idx in valid_indices]
  360. # 如果目标位置在所有待移动元素的最大索引之后,则不需要调整目标位置
  361. max_idx = max(valid_indices)
  362. if max_idx < target_index:
  363. pass
  364. else:
  365. # 计算需要减少的位置数(因为删除元素后,后续元素会向前移动)
  366. shift_count = sum(1 for idx in valid_indices if idx < target_index)
  367. target_index -= shift_count
  368. # 移除元素(从大索引开始以避免影响小索引处的元素)
  369. for idx in reversed(valid_indices):
  370. del lst[idx]
  371. # 插入元素到目标位置,保持它们原来的相对顺序
  372. for i, element in enumerate(elements_to_move):
  373. lst.insert(target_index + i, element)
  374. # 重新写入索引
  375. for index, image_label in enumerate(lst):
  376. image_label.image_index = index
  377. # 比较两个相同格式的时间字符串
  378. def compare_two_times(time_str1, time_str2):
  379. # 定义时间格式
  380. time_format = "%Y-%m-%d %H:%M:%S"
  381. # 将时间字符串解析为datetime对象
  382. time1 = datetime.strptime(time_str1, time_format)
  383. time2 = datetime.strptime(time_str2, time_format)
  384. # 比较两个时间
  385. if time1 > time2:
  386. # print(f"{time_str1} 比 {time_str2} 新。")
  387. return "left_new"
  388. elif time1 < time2:
  389. # print(f"{time_str2} 比 {time_str1} 新。")
  390. return "right_new"
  391. else:
  392. # print("两个时间相等。")
  393. return "is_same"