Python论坛  - 讨论区

标题:[python-chinese] [python] [django] [mod_python] [apache] 再次质疑Django+Mod_python时对环境变量的处理

2008年01月17日 星期四 12:09

憨狗 hackgou在gmail.com
星期四 一月 17 12:09:46 HKT 2008

今天在升级一个django开发的系统到V2的时候,发现~/无法正确的展开成
/home/hackgou.(apache是以hackgou帐号执行的,)也不会展开成/root(apache是以root启动的)
觉得非常奇怪,就算是用os.path.expanduser('~/')也无济于事。
于是怀疑是os.envrion['HOME']不对,因为expanduser是需要这个变量来展开~/的。
于是使用setenv HOME /home/hackgou/
可是也不工作,后来在django/core/handlers/modpython.py的ModPythonHandler中
发现Django开发组已经注意到,mod_python不理会apache的setENV指令:

        # mod_python fakes the environ, and thus doesn't process
SetEnv.  This fixes that
        os.environ.update(req.subprocess_env)

但是这个和SetEnv DJANGO_SETTINGS_MODULE app.settings
自相矛盾矛盾,真晕,自己不设置正确的,也不搭理管理员指定的,怎么办?
后来在http://code.google.com/p/modwsgi/wiki/ApplicationIssues找到一些类似的情况,
提到sudo的时候有bug,会导致HOME和root启动的HOME不一样,太好了,我就要这样的bug。
设置hackgou账号的sudo权限,然后用sudo来启动apache,果然所有的expanduser('~/')都顺利。
除此之外, 文中提到

import os, pwd
os.environ["HOME"] = pwd.getpwuid(os.getuid()).pw_dir

这样的代码,似乎可以解决这个问题,神啊,我很反感这种做法:
1.django中似乎没有地方可以放置这样的需要这个APP都需要的代码,我的DRY啊
2.Django修改环境变量似乎成了习惯,之前碰到个TIME_ZONE的问题,就是因为修改了APACHE的环境变量,导致
别的应用环境受到污染,要知道一个apache进程是很多应用共享的,
除了Djano还有别的应用,比如别的Django应用或者PHP,都有可能在一个相同的APACHE进程空间中处理,
说有可能是因为apache本身的一些设置会出现这些差别,跟py没有关系,
这样会导致他们的工作环境受到污染。这似乎没有好的方法可以解决这个问题,
对Django或者说对mod_python 的这种拖泥带水的做法感觉非常的不爽。
也不知道有没有更好的更彻底的解决方法?
如果谁知道,能够告诉我那是最好不过的了


-- 
关注LAMP平台、安全、及web开发的个人blog: http://hackgou.itbbq.com
PGP KeyID: hackgou#Gmail.com
PGP KeyServ: subkeys.pgp.net

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2008年01月17日 星期四 12:27

Jiahua Huang jhuangjiahua在gmail.com
星期四 一月 17 12:27:55 HKT 2008

本来就不要依赖环境变量,
自己把 ~/ 替换为你的目录吧,


可能的话, scgi/fcgi 替换调 mod_python 会更好些

2008/1/17 憨狗 <hackgou at gmail.com>:
> 今天在升级一个django开发的系统到V2的时候,发现~/无法正确的展开成

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2008年01月17日 星期四 13:25

憨狗 hackgou在gmail.com
星期四 一月 17 13:25:07 HKT 2008

> 本来就不要依赖环境变量,
嗯,没错,那也没有好的办法避免这种hard coding呢?

> 自己把 ~/ 替换为你的目录吧,
>
>
> 可能的话, scgi/fcgi 替换调 mod_python 会更好些
>
> 2008/1/17 憨狗 <hackgou at gmail.com>:
> > 今天在升级一个django开发的系统到V2的时候,发现~/无法正确的展开成
> _______________________________________________
> python-chinese
> Post: send python-chinese at lists.python.cn
> Subscribe: send subscribe to python-chinese-request at lists.python.cn
> Unsubscribe: send unsubscribe to  python-chinese-request at lists.python.cn
> Detail Info: http://python.cn/mailman/listinfo/python-chinese



-- 
关注LAMP平台、安全、及web开发的个人blog: http://hackgou.itbbq.com
PGP KeyID: hackgou#Gmail.com
PGP KeyServ: subkeys.pgp.net

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2008年01月17日 星期四 13:27

Jiahua Huang jhuangjiahua在gmail.com
星期四 一月 17 13:27:43 HKT 2008

把这些弄独立出来,
比如都弄到 conf.py

2008/1/17 憨狗 <hackgou at gmail.com>:
> > 本来就不要依赖环境变量,
> 嗯,没错,那也没有好的办法避免这种hard coding呢?
>
>

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2008年01月17日 星期四 13:37

憨狗 hackgou在gmail.com
星期四 一月 17 13:37:40 HKT 2008

2008/1/17 Jiahua Huang <jhuangjiahua at gmail.com>:
> 把这些弄独立出来,
> 比如都弄到 conf.py
然后再hard coding进去?   :P

> 2008/1/17 憨狗 <hackgou at gmail.com>:
> > > 本来就不要依赖环境变量,
> > 嗯,没错,那也没有好的办法避免这种hard coding呢?
> >
> >
>
> _______________________________________________
> python-chinese
> Post: send python-chinese at lists.python.cn
> Subscribe: send subscribe to python-chinese-request at lists.python.cn
> Unsubscribe: send unsubscribe to  python-chinese-request at lists.python.cn
> Detail Info: http://python.cn/mailman/listinfo/python-chinese



-- 
关注LAMP平台、安全、及web开发的个人blog: http://hackgou.itbbq.com
PGP KeyID: hackgou#Gmail.com
PGP KeyServ: subkeys.pgp.net

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2008年01月17日 星期四 13:41

Jiahua Huang jhuangjiahua在gmail.com
星期四 一月 17 13:41:13 HKT 2008

conf.py 里 homedir = '/home/hackgou'  之类


2008/1/17 憨狗 <hackgou at gmail.com>:
> 2008/1/17 Jiahua Huang <jhuangjiahua at gmail.com>:
> > 把这些弄独立出来,
> > 比如都弄到 conf.py
> 然后再hard coding进去?   :P
>

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2008年01月17日 星期四 13:48

@@ askfor在gmail.com
星期四 一月 17 13:48:21 HKT 2008

×ÜÊǵÃhard codeһЩ¶«Î÷µÄ°É ±ÈÈçDBUSER DBPASSÖ®ÀàµÄ¡£
¶àµã·¾¶Ò²Ã»Ê²Ã´¡£


On 1/17/08, Jiahua Huang <jhuangjiahua在gmail.com> wrote:
>
> conf.py Àï homedir = '/home/hackgou'  Ö®Àà
>
>
> 2008/1/17 º©¹· <hackgou在gmail.com>:
> > 2008/1/17 Jiahua Huang <jhuangjiahua在gmail.com>:
> > > °ÑÕâЩŪ¶ÀÁ¢³öÀ´£¬
> > > ±ÈÈ綼Ūµ½ conf.py
> > È»ºóÔÙhard coding½øÈ¥£¿   :P
> >
> _______________________________________________
> python-chinese
> Post: send python-chinese在lists.python.cn
> Subscribe: send subscribe to python-chinese-request在lists.python.cn
> Unsubscribe: send unsubscribe to  python-chinese-request在lists.python.cn
> Detail Info: http://python.cn/mailman/listinfo/python-chinese
-------------- 下一部分 --------------
Ò»¸öHTML¸½¼þ±»ÒƳý...
URL: http://python.cn/pipermail/python-chinese/attachments/20080117/44ff6207/attachment.html 

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2008年01月17日 星期四 13:59

limodou limodou在gmail.com
星期四 一月 17 13:59:23 HKT 2008

2008/1/17 @@ <askfor在gmail.com>:
> 总是得hard code一些东西的吧 比如DBUSER DBPASS之类的。
> 多点路径也没什么。
>
不是一个简单的hard coding的问题,关键是不要在程序中写死,易变或配置的东西应该独立出来,方便进行修改。

-- 
I like python!
UliPad <>: http://code.google.com/p/ulipad/
meide <>: http://code.google.com/p/meide/
My Blog: http://www.donews.net/limodou

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2008年01月17日 星期四 17:03

vcc vcc在163.com
星期四 一月 17 17:03:04 HKT 2008

> 发现Django开发组已经注意到,mod_python不理会apache的setENV指令:
>
>        # mod_python fakes the environ, and thus doesn't process
> SetEnv.  This fixes that
>        os.environ.update(req.subprocess_env)
>
> 但是这个和SetEnv DJANGO_SETTINGS_MODULE app.settings
> 自相矛盾矛盾,真晕,自己不设置正确的,也不搭理管理员指定的,怎么办?

这个并不自相矛盾,SetEnv不是mod_python处理的,而是mod_env处理的,处理的结果就在req.subprocess_env,只是mod_python并没有赋值给os.environ,所以Django要自己搞一下。问题就在于os.environ.update的时候还putenv了,一般来讲修改过环境变量要恢复回去,Django没有干这个事。给一个小补丁来干这个:

Index: modpython.py
===================================================================
--- modpython.py (revision 7003)
+++ modpython.py (working copy)
@@ -141,6 +141,8 @@

     def __call__(self, req):
         # mod_python fakes the environ, and thus doesn't process SetEnv. 
This fixes that
+        # First save env, after finished restore
+        save_env = os.environ.copy()
         os.environ.update(req.subprocess_env)

         # now that the environ works we can see the correct settings, so 
imports
@@ -166,6 +168,12 @@
                 response = self.apply_response_fixes(request, response)
         finally:
             dispatcher.send(signal=signals.request_finished)
+            osenv = os.environ
+            # restore env
+            for k in osenv.keys():
+                del osenv[k]
+            for k in sav_env:
+                osenv[k] = sav_env[k]

         # Convert our custom HttpResponse object back into the mod_python 
req.
         req.content_type = response['Content-Type']

这样就可以把
import os, pwd
os.environ["HOME"] = pwd.getpwuid(os.getuid()).pw_dir

加到这里面,不违反DRY原则吧 ;-)


> 后来在http://code.google.com/p/modwsgi/wiki/ApplicationIssues找到一些类似的情况,
> 提到sudo的时候有bug,会导致HOME和root启动的HOME不一样,太好了,我就要这样的bug。
> 设置hackgou账号的sudo权限,然后用sudo来启动apache,果然所有的expanduser('~/')都顺利。
> 除此之外, 文中提到
>
> import os, pwd
> os.environ["HOME"] = pwd.getpwuid(os.getuid()).pw_dir
>
> 这样的代码,似乎可以解决这个问题,神啊,我很反感这种做法:
> 1.django中似乎没有地方可以放置这样的需要这个APP都需要的代码,我的DRY啊
> 2.Django修改环境变量似乎成了习惯,之前碰到个TIME_ZONE的问题,就是因为修改了APACHE的环境变量,导致
> 别的应用环境受到污染,要知道一个apache进程是很多应用共享的,
> 除了Djano还有别的应用,比如别的Django应用或者PHP,都有可能在一个相同的APACHE进程空间中处理,
> 说有可能是因为apache本身的一些设置会出现这些差别,跟py没有关系,
> 这样会导致他们的工作环境受到污染。这似乎没有好的方法可以解决这个问题,
> 对Django或者说对mod_python 的这种拖泥带水的做法感觉非常的不爽。
> 也不知道有没有更好的更彻底的解决方法?
> 如果谁知道,能够告诉我那是最好不过的了
>




[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2008年01月17日 星期四 22:44

憨狗 hackgou在gmail.com
星期四 一月 17 22:44:14 HKT 2008

> 这个并不自相矛盾,SetEnv不是mod_python处理的,而是mod_env处理的,处理的结果就在req.subprocess_env,只是mod_python并没有赋值给os.environ,所以Django要自己搞一下。问题就在于os.environ.update的时候还putenv了,一般来讲修改过环境变量要恢复回去,Django没有干这个事。给一个小补丁来干这个:
>
mod_env和mod_python如何处理environ我没有详查,但是经过测试:
未添加setenv时os.path.expanduser("~/")拿到的结果是None
setenv HOEM /home/hackgou之后,os.path.expanduser("~/")拿到的结果是/root,而不是/home/hackgou。
而只有以hackgou用户通过sudo 启动apache时,可以得到正确结果,
此时再设置setenv HOME /home/hackgou,已经不重要了。


> @@ -141,6 +141,8 @@
>
>      def __call__(self, req):
>          # mod_python fakes the environ, and thus doesn't process SetEnv.
> This fixes that
> +        # First save env, after finished restore
> +        save_env = os.environ.copy()
>          os.environ.update(req.subprocess_env)
>
>          # now that the environ works we can see the correct settings, so
> imports
> @@ -166,6 +168,12 @@
>                  response = self.apply_response_fixes(request, response)
>          finally:
>              dispatcher.send(signal=signals.request_finished)
> +            osenv = os.environ
> +            # restore env
> +            for k in osenv.keys():
> +                del osenv[k]
> +            for k in sav_env:
> +                osenv[k] = sav_env[k]
>
>          # Convert our custom HttpResponse object back into the mod_python
> req.
>          req.content_type = response['Content-Type']
>
> 这样就可以把
> import os, pwd
> os.environ["HOME"] = pwd.getpwuid(os.getuid()).pw_dir
>
> 加到这里面,不违反DRY原则吧 ;-)

这样的patch似乎是比较完美的解决办法,破坏现场后恢复现场。我还没有测试过,
不过看其应该没有问题!Very Good!
不知道这个patch有提交么?
另外一个问题,在apache的worker和prefork模式下,是否会影响其他应用,
因为我的理解是worker模式下应该会比较困难,因为所有线程共享相同的系统环境变量共享,
所以我认为相互间肯定会有污染,而在prefork模式下,我就不确定了!
理想状态下,是不应该干扰的。
之所以有这个问题,是因为曾经有过这样的情况:
apache同时支持mod_python和mod_php时。
php中获取本地时间有时候是洛杉矶LA时间有时候是上海时间,
这个服务器在上海,而Django应用的时区需要设置为LA,这个时候就互相影响:
如果这个处理php的进程还没有处理过Django的请求,那么它得到的本地时间是上海时间
如果这个处理php的进程已经处理过Django的请求,那么它得到的本地时间就是LA时间
如果在PHP中设定时区的话,效果是一样的,也会互相干扰。

如果给Django打上这个patch,在prefork情况下,效果如何?
vcc有没有什么建议讲来听听?

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2008年01月18日 星期五 19:46

vcc vcc在163.com
星期五 一月 18 19:46:49 HKT 2008

> 不知道这个patch有提交么?

没有提交,觉得Django设置的环境变量DJANGO_SETTINGS_MODULE一般不会影响到其他应用,如果没修改象时区这样设置的话实在没恢复的必要。

> 另外一个问题,在apache的worker和prefork模式下,是否会影响其他应用,
> 因为我的理解是worker模式下应该会比较困难,因为所有线程共享相同的系统环境变量共享,
> 所以我认为相互间肯定会有污染,而在prefork模式下,我就不确定了!
> 理想状态下,是不应该干扰的。
> 之所以有这个问题,是因为曾经有过这样的情况:
> apache同时支持mod_python和mod_php时。
> php中获取本地时间有时候是洛杉矶LA时间有时候是上海时间,
> 这个服务器在上海,而Django应用的时区需要设置为LA,这个时候就互相影响:
> 如果这个处理php的进程还没有处理过Django的请求,那么它得到的本地时间是上海时间
> 如果这个处理php的进程已经处理过Django的请求,那么它得到的本地时间就是LA时间 
> 
> 如果在PHP中设定时区的话,效果是一样的,也会互相干扰。
>
> 如果给Django打上这个patch,在prefork情况下,效果如何?

prefork应该没问题。
最安全的做法是独立apache,然后透过proxy来对外服务,这样怎么改都不会有影响。

vcc
_ 




[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

如下红色区域有误,请重新填写。

    你的回复:

    请 登录 后回复。还没有在Zeuux哲思注册吗?现在 注册 !

    Zeuux © 2024

    京ICP备05028076号