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

时间:2019-02-14 09:29:40

标签: python file

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

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

printconf = Config('printing.json')

但是,一旦脚本准备好用于生产,就将其放入crontab中,并且crontabroot调用脚本,因此破坏了上面的行。

另外,dev和production显然位于文件系统中的不同位置,所以我什至不能使用绝对路径,因为它们不会相同。

How can I find script's directory with Python?中所述,我可以使用各种方法来查找文件的当前目录。但是,它们的意思是额外的处理,我想知道, 是否有任何Python版本具有(或可能已经计划)任何其他内置方式来告知必须相对于运行脚本的目录找到文件?像__location__一样?

从本质上讲,已经可以对文件引用进行操作,例如导入模块。

此外,我尝试通过__location__添加全局sitecustomize.py变量,但这什至不起作用。

sitecustomize.py:

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

但这也不起作用,因为: -__location__没有传递给脚本, -并且__file__指的是sitecustomize.py

2 个答案:

答案 0 :(得分:0)

首先,您的Dev和Prod环境应该不会有太大差异。这意味着为了保持一致性,您应该为两者使用相同的设置(文件系统,库等)。这样,您的大多数问题都将消失。 如果这样做,则使用硬编码路径是安全的。

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

  1. 按照您的建议使用os.getcwd()__file__
  2. 在运行脚本时使用特定的参数(例如:$SCRIPT_PATH/myscript.py PROD),然后在脚本中基于此参数选择路径。
  3. 仅将专用配置文件用于脚本初始化,将其放在DEV和PROD上的相同位置(我会在/etc/$PROJECT_NAME中建议),并使用特定参数运行脚本(如上文所述)。 / li>

以上方法均不能防止其他与一致性有关的问题,这使我强调您应该考虑使用Docker或Vagrant进行Dev设置(和/或Prod,如果可能)。

答案 1 :(得分:0)

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

大多数问题是由于以下事实:我想确定文件B相对于脚本A的路径,当时使用文件B的实际CALL使用了系统范围的模块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作为第一个参数这一事实而起作用。但是,这是我的主要用例。不确定,否则会起作用。