写了个python脚本,想搞成crontab定时任务,为了方便管理依赖通过pyinstaller打包成可执行文件,但是发现打包后通过__file__变量读取值怎么都不都不是当前路径,最后通过GPT解决了这个问题,在此记录一下:
import datetime
import os
import sys
# 如果直接运行.py文件或打包后的可执行文件,time_log.txt就在当前文件夹
# 但如果cron 定时运行一定要指定绝对路径,相对路径写time_log.txt就会不知道飞到哪里去,由于log写到别的地方了,还没法看log debug
# filename = './time_log.txt'
# 聪明的你想到了使用python动态定位当前文件路径,但却发现pyinstller打包后下面这个路径其实在/tmp/_MEI7kCms2/
# current_file_path = os.path.abspath(__file__)
# current_directory = os.path.dirname(current_file_path)
# filename = os.path.join(current_directory, 'time_log.txt')
# chatGPT给了我如下方案,亲测有效
if getattr(sys, 'frozen', False):
# 如果是打包后的可执行文件,则使用脚本文件目录,用于避免pyinstaller打包后的绝对路径问题
current_directory = os.path.dirname(sys.executable)
else:
# 如果是脚本文件, 则使用当前文件
current_file_path = os.path.abspath(__file__)
current_directory = os.path.dirname(current_file_path)
filename = os.path.join(current_directory, 'time_log.txt')
# 获取当前时间
current_time = datetime.datetime.now()
# 将当前时间格式化为字符串
formatted_time = current_time.strftime('%Y-%m-%d %H:%M:%S')
# 打开文件并追加时间
with open(filename, 'a') as file:
file.write(formatted_time + '\n')
print(f'当前时间已写入到文件:{filename}')
代码逻辑
-
打包后的可执行文件:
if getattr(sys, 'frozen', False): current_directory = os.path.dirname(sys.executable)
如果脚本是打包后的可执行文件,
__file__
变量不可用,sys.frozen
为True
,此时sys.executable
指向可执行文件本身的路径。通过os.path.dirname(sys.executable)
,我们可以获取可执行文件所在的目录。这确保了我们在打包后的环境中能够正确定位到所需的文件和资源。 -
普通 Python 脚本:
else: current_file_path = os.path.abspath(__file__) current_directory = os.path.dirname(current_file_path)
如果脚本是作为普通的 Python 脚本运行,
sys.frozen
为False
,此时我们使用__file__
获取当前脚本文件的路径。通过os.path.abspath(__file__)
获取绝对路径,然后使用os.path.dirname(current_file_path)
获取脚本文件所在的目录。这确保了在开发和调试时,脚本能够正确定位到所需的文件和资源。
总结
crontab要求在代码中写绝对路径
但pyinstaller打包后的python读取的所在文件绝对路径是/tmp, 而不是当前路径
所以分成两种情况,判断是否是打包后的文件,还是.py脚本获取当前文件夹,分情况获取路径