如何在另一个目录中运行 python 脚本,而不将脚本写入磁盘?

Posted

技术标签:

【中文标题】如何在另一个目录中运行 python 脚本,而不将脚本写入磁盘?【英文标题】:How to run python scripts in another directory, without writing scripts to disk? 【发布时间】:2021-04-18 01:56:29 【问题描述】:

假设我有两个 python 脚本 methods.pydriver.pymethods.py 定义了所有方法,driver.py 在我运行它时完成了所需的工作。

假设我在包含两个文件driver.pymethods.py 的主目录中,并且我在主目录中有n 子目录,名为subdir1,subdir2,...,subdirn .所有这些子目录都有作为driver.py 输入的文件。

我要做的是在所有这些子目录中运行 driver.py 并从中获取我的输出,而不将 driver.py 写入磁盘

我应该怎么做? 目前,我正在使用 subprocess 模块来

    将 driver.py 和 methods.py 复制到子目录中。 运行它们。

复制部分很简单:

import subprocess

for i in range(n):
  cmd = "cp methods.py driver.py subdir"+str(i)
  p = subprocess.Popen(cmd, shell=True)
  p.wait()

#once every subdirectory has driver.py and methods.py, start running these codes 

for i in range(n):
  cmd = "cd subdir" + str(i) +" && python driver.py"
  p = subprocess.Popen(cmd, shell=True)
  p.wait()

有没有办法在不占用磁盘空间的情况下完成上述操作?

【问题讨论】:

为什么不修改 driver.py 以接受目录路径?这样,您可以遍历子目录并执行python driver.py /path/to/subdiri。您可能还需要确保 driver.py 代码可以在任何输入目录中运行。 @GinoMempin,哦让它接受整个目录作为输入?我实际上并没有做过这样的事情,但我可以找到一些东西来学习如何做到这一点。谢谢! 【参考方案1】:

扩展my initial comment,而不是到处复制driver.py,你可以让它接受一个子目录的路径作为命令行参数。然后,您还必须确保它可以从任何目录执行它应该执行的任何操作。这意味着要考虑文件的正确路径。

有多种方法可以接受命令行参数(请参阅How to read/process command line arguments?)。为简单起见,我们只使用sys.args 来获取路径。

这是一个修改后的 driver.py

import sys
from pathlib import Path

# Receive the path to the target subdir as command line args
try:
    subdir_path = Path(sys.argv[1]).resolve()
except Exception as e:
    print('ERROR resolving path to subdir')
    print(e)
    sys.exit(1)

# Do stuff, taking into account full path to subdir
print(f'Running driver on subdir_path')
with open(subdir_path.joinpath('input.txt'), 'r') as f:
    data = f.read()
    print(f'Got data = data')

假设在获取路径后,driver.py 期望从每个子目录中读取一个文件 (input.txt)。所以在这里你需要获取子目录的绝对路径 (.resolve()) 并在访问 input.txt (.joinpath()) 时使用它。基本上,认为 driver.py 将始终从 ma​​in 目录运行。

示例用法如下:

main$ tree
.
├── driver.py
├── method.py
├── subdir1
│   └── input.txt
├── subdir2
│   └── input.txt
└── subdir3
    └── input.txt

main$ python driver.py /temp/main/subdir3
Running driver on /temp/main/subdir3
Got data = 3333

现在,在 method.py 中,您不需要“复制 driver.py”代码。只需遍历 ma​​in 下的所有 subdirn 文件夹,然后将完整路径传递给 driver.py。您仍然可以使用相同的 Popen(...) 代码调用 driver.py

这是一个修改后的method.py

import subprocess
from pathlib import Path

# Assume all subdirs are under the current directory
parent_path = Path.cwd()

for child_path in parent_path.iterdir():
    # Skip files/folders not named 'subdirn'
    if not child_path.is_dir() or 'subdir' not in child_path.stem:
        continue

    # iterdir returns full paths (cwd + /subdir)
    print(f'Calling driver.py on child_path')

    cmd = f'python driver.py child_path'
    p = subprocess.Popen(cmd, shell=True)
    p.wait()

示例运行:

main$ python method.py 
Calling driver.py on /temp/main/subdir3
Running driver on /temp/main/subdir3
Got data = 3333

Calling driver.py on /temp/main/subdir2
Running driver on /temp/main/subdir2
Got data = 2222

Calling driver.py on /temp/main/subdir1
Running driver on /temp/main/subdir1
Got data = 1111

还要注意所有的执行都是从 main 完成的。

一些注意事项:

您可以使用iterdir 或其等效的os.listdir 来获取基本路径下的所有文件/文件夹,而不是硬编码range(n),这应该可以方便地返回绝对路径。除非您需要按特定顺序浏览子目录。 我更喜欢使用pathlib 而不是os.path,因为它为文件/文件夹路径提供了更多高级抽象。如果你想或需要使用os.path,有这个table of os.path - pathlib equivalents。 我在这里使用了 f 字符串(参见 What is print(f"...")),它仅适用于 Python 3.6+。如果您使用的是较低版本,只需替换为任何其他字符串格式化方法即可。

【讨论】:

【参考方案2】:

你可以使用 python 的 os.chdir() 函数来改变当前的工作目录:

import os
#import methods

root = os.getcwd()

for d in ['subdir1', 'subdir2']:
  os.chdir(os.path.join(root, d))
  print("dir:", os.getcwd())
  exec(open("../driver.py").read())

我也不确定你是否需要 popen,因为 python 能够使用 exec 函数执行 python 文件。在这种情况下,这取决于您如何导入 methods.py。您是简单地导入它还是在 driver.py 中以其他方式使用它? 您可以尝试在主脚本内的顶层导入它或使用扩展路径,例如:

exec(open("../methods.py").read())

在您的驱动程序脚本中。请记住,这些解决方案都不是很优雅。最好按照 Gino Mempin 的建议处理您的 driver.py 内部的路径。你可以从那里调用 os.chdir()。

【讨论】:

感谢您的回答@areop-enap!我只导入methods.py。 os,chdir(os.path.join(root, d)) 是否将我的目录更改为 subdir1,并 exec(open(...).read()) 运行 driver.py INSIDE subdir1? 是的,我使用仅包含函数调用 open('test.txt','wt').write('test') 的 test.py 对其进行了测试,以确保它正常工作。这样做的问题是:您需要以某种方式包含methods.py,并且由于您将工作目录更改为您的子文件夹,因此您无法通过简单的导入来访问它。您必须先执行 sys.path.append("[absolute path to method.py]"),然后再执行 driver.py 的“导入方法”内幕。您可以在执行 driver.py 之前尝试导入它,但我不确定这是否有效。您的 methods.py 需要以某种方式支持它。

以上是关于如何在另一个目录中运行 python 脚本,而不将脚本写入磁盘?的主要内容,如果未能解决你的问题,请参考以下文章

从 python 生成电影而不将单个帧保存到文件

gnome 终端:找不到目录(在另一个终端中运行 python 脚本)

如何直接在云端上传图片而不将其存储到本地目录中?

如何在python中生成文件而不将其保存到磁盘?

如何在项目中包含/引用文件而不将其复制到项目目录?

如何剥离 Python 日志记录调用而不将它们注释掉?