Closed luyiming closed 3 years ago
有2个问题
抱歉前几天太忙了没回复。 一般来说,命令行程序走不走代理是通过 HTTP_PROXY, HTTPS_PROXY, NO_PROXY 这类环境变量来控制的,也就是如果不设置环境变量的话,命令行程序一般是不走代理的,但是我发现 requests 库好像不仅仅这样,我稍微研究了下。
requests 走代理的判断逻辑主要在 requests/session.py::701
def merge_environment_settings(self, url, proxies, stream, verify, cert):
"""
Check the environment and merge it with some settings.
:rtype: dict
"""
# Gather clues from the surrounding environment.
if self.trust_env:
# Set environment's proxies.
no_proxy = proxies.get('no_proxy') if proxies is not None else None
env_proxies = get_environ_proxies(url, no_proxy=no_proxy)
for (k, v) in env_proxies.items():
proxies.setdefault(k, v)
# Look for requests environment configuration and be compatible
# with cURL.
if verify is True or verify is None:
verify = (os.environ.get('REQUESTS_CA_BUNDLE') or
os.environ.get('CURL_CA_BUNDLE'))
# Merge all the kwargs.
proxies = merge_setting(proxies, self.proxies)
stream = merge_setting(stream, self.stream)
verify = merge_setting(verify, self.verify)
cert = merge_setting(cert, self.cert)
return {'verify': verify, 'proxies': proxies, 'stream': stream,
'cert': cert}
其中 get_environ_proxies(url, no_proxy=no_proxy)
函数最终会调用 getproxies()
来获取代理配置,在 macOS 上它是:
def getproxies():
return getproxies_environment() or getproxies_macosx_sysconf()
在 windows 上它是:
def getproxies():
"""Return a dictionary of scheme -> proxy server URL mappings.
Returns settings gathered from the environment, if specified,
or the registry.
"""
return getproxies_environment() or getproxies_registry()
所以 requests 不仅会受 *_PROXY 这类环境变量控制,还会读取代理软件设置的系统代理配置。所以要不走代理,看起来设置 trust_env=False
是最直接的。这样子也不会对别的程序造成影响。说起来感觉 no_proxy 确实不太必要,我就是担心自己犯蠢一不小心走了代理啥的 233
关于第二个问题,当前配置 details_report.png 确实是相对路径,但是我代码里是有处理的, details_report.py::227
if not os.path.isabs(details_report_path):
details_report_path = os.path.join(task.manager.config_base, details_report_path)
img.save(details_report_path)
这也是参考了 flexget 一些内置插件的做法,在创建 report 的时候,我是可以获取到代码运行目录的,所以相对路径我可以手动给它拼接起来,但是在 telegram mod 里面,我没有办法获取到代码运行目录,所以就没办法处理相对路径问题。 至于 docker 运行没出问题,我猜是因为你的 docker 默认 CWD 路径就是根目录?
flexget 处理 daemon 的代码在 flexget/manager.py
def daemonize(self) -> None:
"""Daemonizes the current process. Returns the new pid"""
if sys.platform.startswith('win'):
logger.error('Cannot daemonize on windows')
return
if threading.active_count() != 1:
logger.critical(
'There are {!r} active threads. Daemonizing now may cause strange failures.',
threading.enumerate(),
)
logger.info('Daemonizing...')
try:
pid = os.fork()
if pid > 0:
# Don't run the exit handlers on the parent
atexit._exithandlers = []
# exit first parent
sys.exit(0)
except OSError as e:
sys.stderr.write(f'fork #1 failed: {e.errno} ({e.strerror})\n')
sys.exit(1)
# decouple from parent environment
os.chdir('/')
os.setsid()
os.umask(0)
...
可以看到它在 daemon 模式会设置当前路径为根目录 /
那其实这个行为就是使用系统代理,很多软件都有类似的行为。总的来说,还是用户的代理设置问题,而且我觉得大多数还是路由级别的代理,这个设置,只能说防止本机的代理软件吧。所以docker化可以避免很多不必要的麻烦。
不过既然有这样的需求,那改一下代码 if 'no_proxy' in entry['site_config']:
最好改成 entry['site_config'].get('no_proxy')
不然 yes 和 no 就没什么意义,临时变量的还原放在finally
至于details_report.png,docker启动是没有加 -d 参数的 也没有必要,所以它不会执行 daemonize
。按我的理解,既然cwd被改成 /
那telegram_mod也应该是去 /
找文件。为什么会出现找不到的情况?
针对这样的情况的话,我认为有2种方式处理
我比较倾向第二种,details_report.png 只相当于一个临时文件,除非发送失败,不然保存的意义不大,用作配置感觉有些多余