有没有更优雅的方式来引用脚本的当前目录?



我有开发环境和生产用于运行crontab中使用的各种Python脚本。

在开发环境中,我通常在脚本目录中的命令行中测试脚本,例如"python myscript.py"。现在,某些脚本从脚本目录的相同或子目录中加载JSON文件的配置。因此,在开发人员中,我可以参考这样的文件:

printconf = Config('printing.json')

但是,一旦脚本准备好生产,它就会放入crontabcrontabroot调用脚本,因此打破上述行。

此外,显然,开发和生产在文件系统中的不同位置,所以我什至无法使用绝对路径,因为它们不会相同。

如我如何与python找到脚本目录中所述?我可以使用各种方法来查找文件当前目录。但是,它们的意思是额外的处理,我想知道,如果任何Python版本可能具有(或可能已经计划过)任何其他内置方法,以说明必须在运行脚本的目录中找到该文件?类似__location__

本质上,可以为文件引用(例如导入模块已经做到的)工作。

此外,我尝试通过sitecustomize.py添加一个全局__location__变量,但这甚至行不通。

sitecustomize.py:

if '__file__' in globals():
    import os
    _location_ = os.path.join(os.getcwd(), os.path.dirname(__file__))

但这也不起作用,因为:-__location__未传递给脚本, - 和__file__sitecustomize.py

首先,您的开发环境和生产环境应该没有太大差异。这意味着,为了一致性,您应该为两者使用相同的设置(文件系统,库等)。这样,您的大多数问题就会消失。如果您这样做,那么使用硬编码路径是安全的。

其他选项(这不可避免地涉及一些处理,但不应是交易破坏者):

  1. 您已经建议使用os.getcwd()__file__
  2. 在运行脚本时使用特定的参数(例如:$SCRIPT_PATH/myscript.py PROD),并根据脚本中的此路径选择路径。
  3. 仅将专用的配置文件用于脚本init,将其放在Dev和prod上的同一位置(我会在/etc/$PROJECT_NAME中建议),并使用特定参数运行脚本(如上所述)。

以上所有方法都不会阻止与一致性相关的其他问题,这使我强调您应该考虑使用Docker或Vagrant进行DEV设置(和/或prod,如有可能)。

当我回顾了这个问题时,很明显,我提供了太多错误的上下文,相关的上下文太少。当我测试实际解决方案时,我决定不重写问题,而是将正确的上下文放在答案中。

大多数问题是由于我想确定文件b的路径相对于脚本A,而实际使用文件B使用了系统范围的模块C(从脚本A中调用)完全不同的地方,这样:

#module C (system-wide in /usr.../site-packages
import os
class Config()
   ...
   def load(file_name):
    # needs to be relative to calling script's dir, not module's!
    real_file_name=os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),file_name)
    ...
#script-A.py ( in /var/scripts/projectA )
from C import Config
conf=Config()
conf.load('file-in-projectA-dir.json')
# finds /var/scripts/projectA/file-in-projectA-dir.json
# regardless of cwd

所以这两者都适用于:

cd /
python3 /var/scripts/projectA/script-A.py
#and:
cd /var/scripts/projectA/
python3 script-A.py
#etc

您可以看到,这仅是由于script-a从命令行称为第一个参数而起作用。但是,这是我的主要用例。不确定,什么可以起作用。

最新更新